|
给出一个有向图,请输出从某一点出发到所有点的最短路径长度。
输入第一行包含三个整数N、M、S,分别表示点的个数、有向边的个数、出发点的编号。接下来M行每行包含三个整数Fi、Gi、Wi,分别表示第i条有向边的出发点、目标点和长度。输出一行,包含N个用空格分隔的整数,其中第i个整数表示从点S出发到点i的最短路径长度(若S=i则最短路径长度为0,若从点S无法到达点i,则最短路径长度为2147483647)
【思路】典型的做法是dijistra,这个我们用邻接表来存图,邻接矩阵虽然直观确实太占空间了。
- #include<iostream>
- using namespace std;
- const int inf=2147483647;
- const int mm=500050;
- const int mn=10010;
- int n,m,s;
- int nxt[mm],ev[mm],ew[mm];
- int dist[mn],vist[mn],nbs[mn],p[mn];
- int getmin()
- {
- int m,k,i;
- m=inf;
- k=0; ///起点,无路可找的时候就返回0
- ///for (i=1;i<=n;i++) cout<<dist[i]<<' '; cout<<endl;
- for (i=1; i<=n; i++)
- if (!vist[i])
- if (dist[i]<m)
- {
- m=dist[i];
- k=i;
- }
- return k;
- }
- void dijkstra(int src)
- {
- int i,j,u,v;
- for(i=1; i<=n; i++)
- {
- dist[i]=inf;
- vist[i]=0;
- };
- dist[src]=0;
- while(1) ///因为是找所有的路,所以这个和标准写法有点不一样
- {
- u=getmin();
- if (u==0) return ; ///靠这句话终结程序
- vist[u]=1;
- for(j=nbs[u]; j!=0; j=nxt[j])
- {
- v=ev[j];
- if(!vist[v]&&dist[u]+ew[j]<dist[v])
- {
- dist[v]=dist[u]+ew[j];
- p[v]=u;
- }
- }
- }
- }
- void printpath(int i)///反推路径找到S到I的路
- {
- int path[mn]={i,}; ///初始终点
- int j=0,k=i;
- while (p[k]!=0) ///完全类似导弹飞机的倒推
- {
- j++;
- path[j]=p[k];
- k=p[k];
- }
- cout<<s<<"-->"<<i<<':';
- for (; j>=0; j--) cout<<path[j];
- cout<<endl;
- }
- int main()
- {
- int i,u,v,w;
- cin>>n>>m>>s;
- for(i=1; i<=n; i++)nbs[i]=0;
- for(i=1; i<=m; i++)
- {
- cin>>u>>v>>w;
- nxt[i]=nbs[u];
- nbs[u]=i;
- ev[i]=v;
- ew[i]=w;///这里考虑一下如何去掉重复的边,
- }
- dijkstra(s);
- for (i=1; i<=n; i++) cout<<dist[i]<<' ';
- ///cout<<endl;
- ///for (i=1; i<=n; i++) printpath(i);
- return 0;
- }
复制代码
|
|