Hdu 2680
这题可以用Spfa算法也可以用Dijkstra算法
Spfa:
Dijkstra:
(时间很明显,前者快多了)
重点是将边方向存储来求。
两种算法的处理有所不同。
Spfa:存的时候反向存
Dijkstra:1、可以反向存也。2、可以将邻接矩阵反过来用。
Dijkstra相对来讲更灵活些。但是在别忘记了处理重边。
PS:网上还存在一种超神的方法,就是创建一个超起点(0)
在初始化时:dis[i]=map[0][i]
处理的时候 cin>>e; map[0][e]=0;
于是最后0->s就是最短路径 即dis[s]; 感觉想出这个方法的人好神。
综上一下,前者在点超过10000时是唯一的方法,不然用邻接矩阵会爆栈。但如果点是小于1000用Dijkstra会更好。
如果坚持邻接矩阵不会爆栈,10000多个点也必然超时,因此Spfa是在打数据是一个很好的选择。
DIjkstra:
#include<iostream> #include<algorithm> #include<stdlib.h> #include<string.h> #include<math.h> #include<string> #include<vector> #include<queue> #include<list> using namespace std; typedef long long lld; typedef unsigned int ud; #define Inf 0xfffffff//int最大 #define Min(x,y) (x)<(y)?(x):(y) #define Max(x,y) (x)>(y)?(x):(y) #define PQ priority_queue #define Q queue #define N 1002 int map[N][N]; int dis[N],mark[N]; int n,m,s; void Dijkstra() { for(int i=1;i<=n;i++) { dis[i]=map[i][s]; mark[i]=0; } dis[s]=0,mark[s]=1; int t=n; while(t--) { int min=Inf; int k; for(int i=1;i<=n;i++) if(!mark[i]&&dis[i]<min) { min=dis[i]; k=i; } if(min==Inf) break; mark[k]=1; for(int i=1;i<=n;i++) if(!mark[i]&&map[i][k]+dis[k]<dis[i]) dis[i]=map[i][k]+dis[k]; } } int main() { while(scanf("%d%d%d",&n,&m,&s)!=EOF) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(i==j) map[i][j]=0; else map[i][j]=Inf; } for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); if(w<map[u][v]) map[u][v]=w; } Dijkstra(); int ans=Inf; int vn; scanf("%d",&vn); while(vn--) { int e; scanf("%d",&e); if(dis[e]<ans) ans=dis[e]; } if(ans==Inf) printf("-1\n"); else printf("%d\n",ans); } return 0; }Spfa
#include<iostream> #include<algorithm> #include<stdlib.h> #include<string.h> #include<math.h> #include<string> #include<vector> #include<queue> #include<list> using namespace std; typedef long long lld; typedef unsigned int ud; #define Inf INT_MAX/2//int最大 #define Min(x,y) (x)<(y)?(x):(y) #define Max(x,y) (x)>(y)?(x):(y) #define PQ priority_queue #define Q queue #define N 1002 #define M 20002 struct Edge { int v,next,w; }edge[M]; int head[N],dis[N],mark[N],cnt[N]; int n,m,s; bool Spfa() { //memset(mark,0,sizeof mark); //memset(cnt,0,sizeof cnt); for(int i=0;i<=n;i++){ dis[i]=Inf; mark[i]=0; cnt[i]=0; } dis[s]=0; mark[s]=1; Q<int> q; q.push(s); while(!q.empty()) { int e=q.front(); q.pop(); mark[e]=0; for(int i=head[e];i!=-1;i=edge[i].next) { int v=edge[i].v; if(dis[v]>dis[e]+edge[i].w) { dis[v]=dis[e]+edge[i].w; if(!mark[v]) { q.push(v); mark[v]=1; if(++cnt[v]>=n) return false; } } } } return true; } int main() { while(scanf("%d%d%d",&n,&m,&s)!=EOF) { //memset(head,-1,sizeof head); for(int i=1;i<=n;i++) head[i]=-1; for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); edge[i].v=u; edge[i].w=w; edge[i].next=head[v]; head[v]=i; } Spfa(); int ans=Inf; int vn; scanf("%d",&vn); while(vn--) { int e; scanf("%d",&e); if(dis[e]<ans) ans=dis[e]; } if(ans==Inf) printf("-1\n"); else printf("%d\n",ans); } return 0; }