多源最短路径
c.floyd
/* 多源最短路径 floyd */ #include<iostream> #include<stdio.h> using namespace std; #define MAXN 1010 #define typec int #define INF 0x3f3f3f3f//防止后面溢出,这个不能太大 int path[MAXN][MAXN]; int cost[MAXN][MAXN],lowcost[MAXN][MAXN]; void floyd(typec cost[][MAXN],typec lowcost[][MAXN],int n){ int i,j,k; for(i=0;i<n;++i) for(j=0;j<n;++j){ lowcost[i][j]=cost[i][j]; if(i!=j&&cost[i][j]<INF)path[i][j]=i; else path[i][j]=-1; } for(k=0;k<n;++k) for(i=0;i<n;++i) for(j=0;j<n;++j) if(lowcost[i][k]+lowcost[k][j]<lowcost[i][j]){ lowcost[i][j]=lowcost[i][k]+lowcost[k][j]; path[i][j]=path[k][j]; } } int main(){ int n,m;//点数,边数 int a,b,w,i,j; int s,t;//起点,终点 while(~scanf("%d%d",&n,&m)){ for(i=0;i<n;++i) for(j=0;j<n;++j) cost[i][j]=INF; for(i=0;i<m;++i){ scanf("%d%d%d",&a,&b,&w); if(w<cost[a][b])cost[a][b]=cost[b][a]=w;// } scanf("%d%d",&s,&t); floyd(cost,lowcost,n); if(s==t)printf("0 "); else if(lowcost[s][t]!=INF)printf("%d ",lowcost[s][t]); else printf("-1 "); } return 0; }
-----------------------
c.Dijkstra单源最短路
/* Dijkstra单源最短路 权值必须是非负 单源最短路径,Dijkstra算法,邻接矩阵形式,复杂度为O(n^2) 求出源beg到所有点的最短路径,传入图的顶点数,和邻接矩阵cost[][] 返回各点的最短路径lowcost[],路径pre[].pre[i]记录beg到i路径上的父结点,pre[beg]=-1 可更改路径权类型,但是权值必须为非负 */ #include<iostream> #include<stdio.h> using namespace std; const int MAXN=1010; #define typec int const typec INF=0x3f3f3f3f;//防止后面溢出,这个不能太大 bool vis[MAXN]; int pre[MAXN]; void Dijkstra(typec cost[][MAXN],typec lowcost[],int n,int beg){ for(int i=0;i<n;i++){ lowcost[i]=INF;vis[i]=false;pre[i]=-1; } lowcost[beg]=0; for(int j=0;j<n;j++){ int k=-1; int Min=INF; for(int i=0;i<n;i++) if(!vis[i]&&lowcost[i]<Min){ Min=lowcost[i]; k=i; } if(k==-1)break; vis[k]=true; for(int i=0;i<n;i++) if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i]){ lowcost[i]=lowcost[k]+cost[k][i]; pre[i]=k; } } } int main(){ return 0; }
c2.Dijkstra算法+堆优化
/* Dijkstra算法+堆优化 使用优先队列优化,复杂度O(E log E) 使用优先队列优化Dijkstra算法 复杂度O(E log E) 注意对vector<Edge>E[MAXN]进行初始化后加边 */ #include<iostream> #include<stdio.h> #include<vector> #include<string.h> #include<queue> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=1000010; struct qnode{ int v; int c; qnode(int _v=0,int _c=0):v(_v),c(_c){} bool operator <(const qnode &r)const{ return c>r.c; } }; struct Edge{ int v,cost; Edge(int _v=0,int _cost=0):v(_v),cost(_cost){} }; vector<Edge>E[MAXN]; bool vis[MAXN]; int dist[MAXN]; //点的编号从1开始 void Dijkstra(int n,int start){ memset(vis,false,sizeof(vis)); for(int i=1;i<=n;i++)dist[i]=INF; priority_queue<qnode>que; while(!que.empty())que.pop(); dist[start]=0; que.push(qnode(start,0)); qnode tmp; while(!que.empty()){ tmp=que.top(); que.pop(); int u=tmp.v; if(vis[u])continue; vis[u]=true; for(int i=0;i<E[u].size();i++){ int v=E[tmp.v][i].v; int cost=E[u][i].cost; if(!vis[v]&&dist[v]>dist[u]+cost){ dist[v]=dist[u]+cost; que.push(qnode(v,dist[v])); } } } } void addedge(int u,int v,int w){ E[u].push_back(Edge(v,w)); } int main(){ return 0; }
c3.单源最短路bellman_ford算法
/* 单源最短路bellman_ford算法 单源最短khtkbellman_ford算法,复杂度O(VE) 可以处理负边权图。 可以判断是否存在负环回路。返回true,当且仅当图中不包含从源点可达的负权回路 vector<Edge>E;先E.clear()初始化,然后加入所有边 点的编号从1开始(从0开始简单修改就可以了) */ #include<iostream> #include<stdio.h> #include<vector> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=550; int dist[MAXN]; struct Edge{ int u,v; int cost; Edge(int _u=0,int _v=0,int _cost=0):u(_u),v(_v),cost(_cost){} }; vector<Edge>E; //点的编号从1开始 bool bellman_ford(int start,int n){ for(int i=1;i<=n;i++)dist[i]=INF; dist[start]=0; //最多做n-1次 for(int i=1;i<n;i++){ bool flag=false; for(int j=0;j<E.size();j++){ int u=E[j].u; int v=E[j].v; int cost=E[j].cost; if(dist[v]>dist[u]+cost){ dist[v]=dist[u]+cost; flag=true; } } if(!flag)return true;//没有负环回路 } for(int j=0;j<E.size();j++) if(dist[E[j].v]>dist[E[j].u]+E[j].cost) return false;//有负环回路 return true;//没有负环回路 } int main(){ return 0; }
c4.单源最短路SPFA
/* 单源最短路SPFA 时间复杂度O(kE) 这个是队列实现,有时候改成栈实现会更加快,很容易修改 这个复杂度是不定的 */ #include<iostream> #include<stdio.h> #include<vector> #include<string.h> #include<queue> using namespace std; const int MAXN=1010; const int INF=0x3f3f3f3f; struct Edge{ int v; int cost; Edge(int _v=0,int _cost=0):v(_v),cost(_cost){} }; vector<Edge>E[MAXN]; void addedge(int u,int v,int w){ E[u].push_back(Edge(v,w)); } bool vis[MAXN];//在队列标志 int cnt[MAXN];//每个点的入队列次数 int dist[MAXN]; bool SPFA(int start,int n){ memset(vis,false,sizeof(vis)); for(int i=1;i<=n;i++)dist[i]=INF; vis[start]=true; dist[start]=0; queue<int>que; while(!que.empty())que.pop(); que.push(start); memset(cnt,0,sizeof(cnt)); cnt[start]=1; while(!que.empty()){ int u=que.front(); que.pop(); vis[u]=false; for(int i=0;i<E[u].size();i++){ int v=E[u][i].v; if(dist[v]>dist[u]+E[u][i].cost){ dist[v]=dist[u]+E[u][i].cost; if(!vis[v]){ vis[v]=true; que.push(v); if(++cnt[v]>n)return false; //cnt[i] 为入队列次数,用来判定是否存在负环回路 } } } } return true; } int main(){ return 0; }