图论算法-建图和最短路

建图方法:

详细参见http://blog.csdn.net/stay_accept/article/details/50886067

常见两种:

链接表法

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <iostream>  
#include <algorithm>  
using namespace std;  
int N,M;  
struct node{  
    int to,w;  
    node *next;  
};  
struct edge{  
    node *first;  
}G[105];  //存第一条边
int main(){  
    int i,j,x,y,z;  
    scanf("%d%d",&N,&M);  
    for(i=0;i<M;i++){  
        scanf("%d%d%d",&x,&y,&z);  
        node *p=new node;  
        p->to=y;  
        p->w=z;  
        p->next=G[x].first;                     //每条边连在当前节点的前一条边上  
        G[x].first=p;                           //形成一个链式储存结构,first为当前节点的最后  
    }                                           //一条边  
    node *k;  
    for(i=1;i<=N;i++){                          //图的遍历  
        for(k=G[i].first;k!=NULL;k=k->next)       
        printf("%d %d %d\n",i,k->to,k->w);  
    }  
    return 0;  
}  


vector 建图(以网络流建图为例)

struct Node
{
	int to;//终点  
	int cap;//容量
	int flow=0;
	int rev; //反向点
	int cost; //费用
};
typedef vector<Node>* Graph;
void add_Node(Graph v,int from, int to, int cap,int cost)  //加边  
{
	Node nodefrom,nodeto;
	nodefrom.to = to, nodefrom.cap =cap,nodefrom.rev = v[to].size(),nodefrom.cost = cost;
	v[from].push_back(nodefrom);
	nodeto.to = from, nodeto.cap =cap, nodeto.rev = v[from].size()-1,nodeto.cost =cost;
	v[to].push_back(nodeto);
}


最短路算法Dijkstra

//Dijkstra求单源最短路径  
void Dijkstra(Graph G,int Vcount,int s,int path[],int dist[]){      //Vcount:顶点个数;s:开始结点;path[]用于返回由开始结点到相应结点的路径指示  
    int i,j,w,minc,dist[Vcount],mark[Vcount];  //mark记录是否访问过
    memset(mark,0,Vcount); //开始都没有访问过 
    for(i=0;i<Vcount;i++){  
        dist[i]=G[s][i];  
        path[i]=s;  
    }     //初始化,不可达的话设置为无穷
    mark[s]=1;path[s]=0;dist[s]=0;  
    for(i=1;i<Vcount;i++){  
        minc=INFINITY;  
        w=0;  
        for(j=0;j<Vcount;j++)  
            if(!mark[j] && minc>=dist[j]){  
                minc=dist[j];  
                w=j;  //找出目前到达最小的边
            }  
        mark[w]=1;  //访问
        for(j=0;j<Vcount;j++)  
            if(!mark[j] && G[w][j]!=INFINITY && dist[j]>dist[w]+G[w][j]){  
                dist[j]=dist[w]+G[w][j];  
                path[j]=w;  //可松弛更新
            }  
    }  
}  
//注意:输入的图的边的权值必须非负(这是Dijkstra的局限性所在).  
floyd算法

void Floyd_Warshall(Graph G,int Vcount,Graph D,Graph P){        //D:D[i][j]表示从i到j的最短距离;P:P[i][j]表示从i到j的最短路径上的结点  
    int i,j,k;  
    for(i=0;i<Vcount;i++)  
        for(j=0;j<Vcount;j++){  
            D[i][j]=G[i][j];  
            P[i][j]=i;  
        }  //用这个算法最好用矩阵建图,初始化
    for(i=0;i<Vcount;i++){  
        D[i][i]=0;  
        P[i][i]=0;  
    }  //注意对角线初始化0
    for(k=0;k<Vcount;k++)  
        for(i=0;i<Vcount;i++)  
            for(j=0;j<Vcount;j++)  
                if(D[i][j]>D[i][k]+D[k][j]){  
                    D[i][j]=D[i][k]+D[k][j];  
                    P[i][j]=P[k][j];  
                }  //比较所有i经过点k然后再到j的距离
}  


bellmanford 算法

bool BellmanFord( int s )  
{  
    for( int i = 0; i < n; i ++ )  
        dis[i] = inf;  
    dis[s] = 0;  
    for( int i = 0; i < n-1; i ++ )  //n-1次松弛  
    {  
        for( int j = 0; j < n; j ++ ) //每一次对所有边操作 
        {  
            if( dis[j] == inf )  
                continue;  
            for( int k = 0; k < map[j].size(); k ++ )  
            {  
                node u = map[j][k];  
                if( u.w != inf && dis[u.id] > dis[j] + u.w )  
                    dis[u.id] = dis[j] + u.w;  
            }  
        }  
    }  
    for( int j = 0; j < n; j ++ )  
    {  
        if( dis[j] == inf )  
            continue;  
        for( int k = 0; k < map[j].size(); k ++ )  
        {  
            node u = map[j][k];  
            if( u.w != inf && dis[u.id] > dis[j] + u.w )  
                return false;  
        }  
    }  //检查负值圈
    return true;  
}  

SPFA 算法(bellman优化)

void SPFA(int v0)  
{  
    memset(vis, false, sizeof(vis));  
    for(int i = 1; i <= n; i++)  
        dis[i] = INF;  
    dis[v0] = 0;  
    queue <int> q;  
    q.push(v0);  
    while(!q.empty())  
    {  
        int u = q.front();  
        q.pop();  
        vis[u] = false;  
        int sz = vt[u].size();  
        for(int i = 0; i < sz; i++)  
        {  
            int v = vt[u][i].v;  
            int w = vt[u][i].w;  
            if(dis[v] > dis[u] + w)  
            {  
                dis[v] = dis[u] + w;  
                if(!vis[v])  
                {  
                    q.push(v);  
                    vis[v] = true;  
                }  
            }  
        }  
    }  
}  









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值