题目:
3 3 0 1 1 0 2 3 1 2 1 0 2 3 1 0 1 1 1 2
2 -1
spfa算法:Bellman-Ford算法基于动态规划,不断用已有的边更新最短距离,if dis[edge[k].to]>dis[j]+edge[k].w则dis[edge[k].to]=dis[j]+edge[k].w; spfa在此基础上做出了改进,用队列和标记数组进行优化,标记过了的点不会被放进队列了,函数是针对从队列中的取出的点进行相连点发散遍历,且每次遍历如果发现了更短的路径都及时的把目的地相应点标记了,这样相比Dijkstra的从头至尾遍历找一条最短路径标记目的地的相应点,再遍历更新要快,如果某一个点出队列的次数大于n-1则判定存在负环。
#include <iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int maxn=205,INF=0x3f3f3f3f; queue<int> q; int n,map[maxn][maxn],dis[maxn]; bool spfa(int s){ bool vis[maxn]; int i,k,out[maxn]; for(i=0;i<n;i++)dis[i]=INF; memset(vis,0,sizeof(vis)); memset(out,0,sizeof(out)); q.push(s); vis[s]=1; dis[s]=0; while(!q.empty()){ int t=q.front(); q.pop(); vis[t]=0; out[t]++; if(out[t]>n-1)return false; //本题没有负权值的问题,这里可以不写判断 for(i=0;i<n;i++){ if(dis[i]>dis[t]+map[t][i]){ dis[i]=dis[t]+map[t][i]; if(!vis[i]){ vis[i]=1; q.push(i); } } } } return true; } int main() { //freopen("cin.txt","r",stdin); int m,i,j; while(cin>>n>>m){ for(i=0;i<n;i++){ for(j=0;j<n;j++){ map[i][j]=(i==j?0:INF); //i==j-->0 } } for(i=0;i<m;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); if(map[a][b]>c){ //要预防a1,b1,c1; a1,b1,c2 c2<c1这类的奇葩数据 map[a][b]=c; //,所以相比链式前向星更推荐邻接矩阵 map[b][a]=c; } } int s,e; scanf("%d%d",&s,&e); if(spfa(s)){ //本题肯定true if(dis[e]==INF)printf("-1\n"); else printf("%d\n",dis[e]); } } return 0; }
#include <iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn=205,INF=0x3f3f3f3f; int n,map[maxn][maxn],dis[maxn][maxn],pre[maxn][maxn]; //dis记录不同点间的最短路径长度, void floyd(){ //pre记录从i到j路径中j的前一节点 int i,j,k; for(i=0;i<n;i++){ for(j=0;j<n;j++){ dis[i][j]=map[i][j]; pre[i][j]=i; } } for(k=0;k<n;k++){ for(i=0;i<n;i++){ for(j=0;j<n;j++){ dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); pre[i][j]=pre[k][j]; } } } } int main() { //freopen("cin.txt","r",stdin); int m,i,j; while(cin>>n>>m){ for(i=0;i<n;i++){ for(j=0;j<n;j++){ map[i][j]=(i==j?0:INF); } } for(i=0;i<m;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); map[a][b]=map[b][a]=min(map[a][b],c); } int s,e; scanf("%d%d",&s,&e); floyd(); printf("%d\n",dis[s][e]<INF?dis[s][e]:-1); } return 0; }
#include <iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn=205,INF=0x3f3f3f3f; int n,map[maxn][maxn]; void floyd(){ for(int k=0;k<n;k++){ for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ map[i][j]=min(map[i][j],map[i][k]+map[k][j]); } } } } int main() { //freopen("cin.txt","r",stdin); int m,i,j; while(cin>>n>>m){ for(i=0;i<n;i++){ for(j=0;j<n;j++){ map[i][j]=(i==j?0:INF); //当i==j时一定要等于0。 } } for(i=0;i<m;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); map[a][b]=map[b][a]=min(map[a][b],c); } int s,e; scanf("%d%d",&s,&e); floyd(); printf("%d\n",map[s][e]<INF?map[s][e]:-1); } return 0; }