poj2387
题目名称:Til the Cows Come Home
题目链接:http://poj.org/problem?id=2387
题意:有N个点,T条边,问从1->N的最短路径
注意:INF不能设置太大,因为加法时可能溢出变负数,所以设为比最大值大一点就行,如10条最大1000的边则设置为10*1000+1(注意不是一条边的最大,是全部边和的最大)
思路:模板题,然后记得有重边
代码如下:只有dijkstra要判重边,spfa不用,,一般用spfa,负权可以用
dijkstra (O(n^2))
#include<cstdio> #include<cstring> #include<iostream> #include<string> #include<algorithm> #include<map> #include<vector> #include<queue> using namespace std; const int maxn=1005; const int INF=0x3f3f3f3f; int dis[maxn][maxn]={INF}; int t,n; int dijkstra() { int d[maxn]; bool vis[maxn]={false}; memset(d,INF,sizeof(d)); d[1]=0; for(int i=1;i<=n;i++) { int x,m=INF; for(int j=1;j<=n;j++) { if(!vis[j]&&d[j]<=m) { m=d[j]; x=j; } } vis[x]=true; for(int j=1;j<=n;j++) { d[j]=min(d[j],d[x]+dis[x][j]); } } return d[n]; } int main() { while(scanf("%d%d",&t,&n)!=EOF) { memset(dis,INF,sizeof(dis)); int from,to,dist; for(int i=0;i<t;i++) { scanf("%d%d%d",&from,&to,&dist); if(dist<dis[from][to]) //判重边 { dis[from][to]=dist; dis[to][from]=dist; } } printf("%d\n",dijkstra()); } return 0; }
邻接矩阵vector版的spfa
#include<cstdio> #include<string> #include<queue> #include<iostream> #include<cstring> #include<vector> using namespace std; const int maxn=1005; const int INF=0x3f3f3f3f; int dis[maxn][maxn]={INF}; //记录权值 bool inque[maxn]; //记录是否在队列中 int d[maxn]; //记录最短路 int t,n; vector<int> vr[maxn]; void spfa(int s) { for(int i=1;i<=n;i++) { d[i]=INF; inque[i]=false; } queue<int> Q; d[s]=0; inque[s]=true; Q.push(s); while(!Q.empty()) { int x=Q.front(); Q.pop(); inque[x]=false; for(int i=0;i<vr[x].size();i++) { int y=vr[x][i]; if(d[y]>d[x]+dis[x][y]) { d[y]=d[x]+dis[x][y]; if(!inque[y]) { inque[y]=true; Q.push(y); } } } } } int main() { while(scanf("%d%d",&t,&n)!=EOF) { memset(dis,INF,sizeof(dis)); int from,to,dist; for(int i=0;i<t;i++) { scanf("%d%d%d",&from,&to,&dist); if(dist<dis[from][to]) { dis[from][to]=dist; dis[to][from]=dist; } vr[from].push_back(to); vr[to].push_back(from); } spfa(1); printf("%d\n",d[n]); } return 0; }
邻接表的spfa
#include<cstdio> #include<string> #include<queue> #include<iostream> #include<cstring> using namespace std; const int maxn=2005; const int INF=0x3f3f3f3f; //int dis[maxn][maxn]={INF}; //记录权值 bool inque[maxn]; //记录是否在队列中 int d[maxn]; //记录最短路 int t,n; int head[maxn]; struct Edge { int v,w,next; //v记录这一条边下个点,w记录该边的权值,next记录在这个点上的下一条边 }edge[maxn*2]; int cnt; void add_edge(int u,int v,int w) { edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } void init() { cnt=0; memset(head,-1,sizeof(head)); memset(inque,false,sizeof(inque)); // memset(dis,INF,sizeof(dis)); memset(d,INF,sizeof(d)); } void spfa(int s) { queue<int> Q; d[s]=0; Q.push(s); inque[s]=true; while(!Q.empty()) { int u=Q.front(); Q.pop(); inque[u]=false; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; int w=edge[i].w; if(d[v]>d[u]+w) { d[v]=d[u]+w; if(!inque[v]) { inque[v]=true; Q.push(v); } } } } } int main() { while(scanf("%d%d",&t,&n)!=EOF) { int from,to,dist; init(); for(int i=0;i<t;i++) { scanf("%d%d%d",&from,&to,&dist); add_edge(from,to,dist); add_edge(to,from,dist); } spfa(1); printf("%d\n",d[n]); } return 0; }
//这道题红果果的超时了。。
#include<cstdio> #include<string> #include<queue> #include<iostream> #include<cstring> using namespace std; const int maxn=1005; const int INF=0x3f3f3f3f; int d[maxn][maxn]; int n,t; void floyd() { for(int k=1;k<=n;k++) //注意先k,i和j的顺序可以变 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); } int main() { while(scanf("%d%d",&t,&n)!=EOF) { int from,to,dist; memset(d,INF,sizeof(d)); for(int i=1;i<=t;i++) { scanf("%d%d%d",&from,&to,&dist); if(dist<d[from][to]) { d[from][to]=dist; d[to][from]=dist; } } for(int i=1;i<=n;i++) { d[i][i]=0; } floyd(); printf("%d\n",d[1][n]); } return 0; }
本文版权归作者本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.