最短路径模板
适应对象:有权图(有向或无向都行)
图存储方式:邻接矩阵(有0和INF的那种,否则就over)
一、Floyd算法:
1。核心代码:
void floyd() { int i,j,k; for(i=0;i<g.n;i++) for(j=0;j<g.n;j++) { dist[i][j]=g.edges[i][j]; if(i!=j&&g.edges[i][j]<inf) path[i][j]=i;//有路 else path[i][j]=-1;// } for(k=0;k<g.n;k++) for(i=0;i<g.n;i++) for(j=0;j<g.n;j++) if(dist[i][j]>dist[i][k]+dist[k][j]) { dist[i][j]=dist[i][k]+dist[k][j]; path[i][j]=path[k][j]; } }
2.完整代码(题目地址:http://tk.hustoj.com/problem.php?id=1120)
#include<iostream> using namespace std; const int maxn=10; const int inf=32767; class Graph { struct matgraph { int n; int edges[maxn][maxn]; }; matgraph g; int dist[maxn][maxn];//存路径长度,比如dist[1][2]就是1->2的最短路径 int path[maxn][maxn];//具体路径 public : void make_matgraph(int n) { int m; g.n=n; cin>>m; for(int i=0;i<g.n;i++) for(int j=0;j<g.n;j++) if(i==j) g.edges[i][j]=0; else g.edges[i][j]=inf; for(int i=0;i<m;i++) { int a,b,c; cin>>a>>b>>c; g.edges[a-1][b-1]=c; g.edges[b-1][a-1]=c; } } void floyd() { int i,j,k; for(i=0;i<g.n;i++) for(j=0;j<g.n;j++) { dist[i][j]=g.edges[i][j]; if(i!=j&&g.edges[i][j]<inf) path[i][j]=i;//有路 else path[i][j]=-1;// } for(k=0;k<g.n;k++) for(i=0;i<g.n;i++) for(j=0;j<g.n;j++) if(dist[i][j]>dist[i][k]+dist[k][j]) { dist[i][j]=dist[i][k]+dist[k][j]; path[i][j]=path[k][j]; } } void ask() { int a,b; cin>>a>>b; a--; b--; if(dist[a][b]!=inf) { cout<<dist[a][b]<<endl; /* cout<<"路径:\n"; do { cout<<b+1<<" "; b=path[a][b]; }while(b!=-1);*/ } else cout<<"No path"<<endl; } }; int main() { Graph g; int n; while(cin>>n) { g.make_matgraph(n); g.floyd(); g.ask(); } return 0; }
二、Dijkstra算法
1.邻接表实现
a.核心代码:
void dijkstra(const adjgraph g,int s,int t) { double dist[maxn]={0}; int visited[maxn]={0};//标记是否拜访 int path[maxn]; for(int i=1;i<=g.n;i++) { dist[i]=(double)inf; path[i]=-1; } visited[s]++; dist[s]=0; arcnode *p=g.adjlist[s].firstarc; while(p!=NULL) { dist[p->adjvex]=p->weight; path[p->adjvex]=s; p=p->nextarc; } for(int i=1;i<g.n;i++) { double minn=(double)inf; int u; for(int j=1;j<=g.n;j++) if(!visited[j]&&dist[j]<minn)//对未拜访的点进行比较 { minn=dist[j]; u=j; } visited[u]++; arcnode *p=g.adjlist[u].firstarc; while(p!=NULL)//用新的点去更新路径 { if(!visited[p->adjvex]&& p->weight+minn<dist[p->adjvex])//lowcost 表示未拜访 { dist[p->adjvex]=p->weight+minn; path[p->adjvex]=u; } p=p->nextarc; } } printf("%0.2lf\n",dist[t]); }
b.完整代码:(题目地址:http://120.77.243.165/problem.php?id=3974)
#include<iostream> #include<algorithm> #include<cstdio> #include<cmath> using namespace std; const int maxn=100; const int inf=32767; struct arcnode { int adjvex; double weight; arcnode *nextarc; }; struct vnode { arcnode *firstarc; }; struct adjgraph { int n; vnode adjlist[maxn]; }; struct vertex { int x; int y; }; double get_weight(vertex a,vertex b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } void make_adjgraph(adjgraph &g) { int m; vertex dist[maxn];//存储坐标 cin>>g.n; for(int i=1;i<=g.n;i++)//Initial g.adjlist[i].firstarc=NULL; for(int i=1;i<=g.n;i++) cin>>dist[i].x >>dist[i].y; cin>>m; for(int i=0;i<m;i++) { int a,b; cin>>a>>b; double weight=get_weight(dist[a],dist[b]); arcnode *p=new arcnode; p->adjvex=b; p->weight=weight; p->nextarc=g.adjlist[a].firstarc; g.adjlist[a].firstarc=p; p=new arcnode; p->adjvex=a; p->weight=weight; p->nextarc=g.adjlist[b].firstarc; g.adjlist[b].firstarc=p; } } void dijkstra(const adjgraph g,int s,int t) { double dist[maxn]={0}; int visited[maxn]={0};//标记是否拜访 int path[maxn]; for(int i=1;i<=g.n;i++) { dist[i]=(double)inf; path[i]=-1; } visited[s]++; dist[s]=0; arcnode *p=g.adjlist[s].firstarc; while(p!=NULL) { dist[p->adjvex]=p->weight; path[p->adjvex]=s; p=p->nextarc; } for(int i=1;i<g.n;i++) { double minn=(double)inf; int u; for(int j=1;j<=g.n;j++) if(!visited[j]&&dist[j]<minn)//对未拜访的点进行比较 { minn=dist[j]; u=j; } visited[u]++; arcnode *p=g.adjlist[u].firstarc; while(p!=NULL)//用新的点去更新路径 { if(!visited[p->adjvex]&& p->weight+minn<dist[p->adjvex])//lowcost 表示未拜访 { dist[p->adjvex]=p->weight+minn; path[p->adjvex]=u; } p=p->nextarc; } } printf("%0.2lf\n",dist[t]); } int main() { adjgraph g; make_adjgraph(g); int s ,t; cin>>s>>t; dijkstra(g,s,t); return 0; }
2.邻接矩阵实现
a.核心代码:
void dijkstra(int v) { int visit[maxn]={0};//记录是否拜访 for(int i=1;i<=g.n;i++) { dist[i]=g.edges[v][i]; if(dist[i]!=inf&&i!=v) path[i]=v; else path[i]=-1; } visit[v]++; for(int i=1;i<g.n-1;i++) { double minn=inf; int u; for(int j=1;j<=g.n;j++) if(!visit[j]&&dist[j]<minn) { u=j; minn=dist[j]; } visit[u]++; for(int j=1;j<=g.n;j++) { if(!visit[j]&&minn+g.edges[u][j]<dist[j]) { dist[j]=minn+g.edges[u][j]; path[j]=u; } } } }
b.完整代码:(题目地址:http://120.77.243.165/problem.php?id=3974)
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; const int maxn=100; const double inf=32767; class Graph { struct matgraph { int n; double edges[maxn][maxn]; }; struct vertex { int x; int y; }; vertex coord[maxn]; matgraph g; double dist[maxn]; int path[maxn]; public: double get_weight(int a,int b) { return sqrt((coord[a].x-coord[b].x)*(coord[a].x-coord[b].x)+(coord[a].y-coord[b].y)*(coord[a].y-coord[b].y)); } void make_matgraph() { cin>>g.n; for(int i=1;i<=g.n;i++) for(int j=1;j<=g.n;j++) if(i==j) g.edges[i][j]=0; else g.edges[i][j]=inf; for(int i=1;i<=g.n;i++) cin>>coord[i].x>>coord[i].y; int m; cin>>m; for(int i=0;i<m;i++) { int a,b; cin>>a>>b; double weight=get_weight(a,b); g.edges[a][b]=weight; g.edges[b][a]=weight; } } void dijkstra(int v) { int visit[maxn]={0};//记录是否拜访 for(int i=1;i<=g.n;i++) { dist[i]=g.edges[v][i]; if(dist[i]!=inf&&i!=v) path[i]=v; else path[i]=-1; } visit[v]++; for(int i=1;i<g.n-1;i++) { double minn=inf; int u; for(int j=1;j<=g.n;j++) if(!visit[j]&&dist[j]<minn) { u=j; minn=dist[j]; } visit[u]++; for(int j=1;j<=g.n;j++) { if(!visit[j]&&minn+g.edges[u][j]<dist[j]) { dist[j]=minn+g.edges[u][j]; path[j]=u; } } } } void ask_distance(int t) { printf("%0.2lf\n",dist[t]); /*cout<<"路径:"<<t<<" "; while(path[t]!=-1) { cout<<path[t]<<" "; t=path[t]; } cout<<endl;*/ } }; int main() { Graph a; a.make_matgraph(); int s,t; cin>>s>>t; a.dijkstra(s); a.ask_distance(t); return 0; }