一:dijkstra模板(n2)
int dis[maxn],vis[maxn]; void dijkstra(int src) { int i,k,j,tmp; for(i=1;i<=n;++i) dis[i]=mt[src][i],vis[i]=0; dis[src]=0; vis[src]=1; for(i=0;i<n-1;++i){//n个点选n-1条边 tmp=INF; for(j=1;j<=n;++j){//取出此时最短距离 if(!vis[j]&&tmp>=dis[j]){ k=j;tmp=dis[j]; } } if(tmp==INF) break;//无最短距离-无解 vis[k]=1; for(j=1;j<=n;++j){ if(!vis[j]&&dis[j]>dis[k]+mt[k][j]) dis[j]=dis[k]+mt[k][j];//更新src到j的距离 } } }
二:floyd弗洛伊德(n3)
for(int k=1; k<=n; ++k) { for(int i=1; i<=n; ++i) { for(int j=1; j<=n; ++j) { if(arr[i][k]+arr[k][j]<arr[i][j])//判断是否更新距离 arr[i][j]=arr[i][k]+arr[k][j]; } } }
1.使用floyd时记得初始化距离
for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) arr[i][j]= {i==j?0:INF};
2.floyd的单点修改后更新最短距离:Roads in Berland
题目大意:给出个点距离矩阵后,如若要修改某个距离,每次修改后回答每对点之间最短距离和
ll dis[maxn][maxn]; int n,m; int main() { cin>>n; for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j) cin>>dis[i][j]; } int k;cin>>k; while(k--){ int x,y,val;cin>>x>>y>>val; if(dis[x][y]>val) dis[x][y]=dis[y][x]=val;//修改两点距离 for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) dis[i][j]=min(dis[i][j],min(dis[i][x]+dis[x][j],dis[i][y]+dis[y][j])),dis[j][i]=dis[i][j];//更新每个经过这条边的最短距离 ll ans=0; for(int i=1;i<=n;++i) for(int j=1;j<i;++j) ans+=dis[i][j];//求每对点之间的最短距离和 cout<<ans<<endl; } }
dijkstra经典例题:find the safest road-求最安全的路-'最短路'变形,此题变为乘法计算
const int maxn=1010; int n;int s,e; double m[maxn][maxn],dis[maxn]; int vis[maxn]; void dij() { int i,j,k; double tmp; for(i=1;i<=n;++i) dis[i]=m[s][i],vis[i]=0; dis[s]=1;vis[s]=1; for(i=0;i<n-1;++i){ tmp=0;k=-1; for(j=1;j<=n;++j) if(!vis[j]&&dis[j]>tmp) tmp=dis[j],k=j; if(tmp==0) break; vis[k]=1; for(j=1;j<=n;++j) if(!vis[j]&&dis[k]*m[k][j]>dis[j])//此处略有修改算的是乘法求最安全的路 dis[j]=dis[k]*m[k][j]; } } int main() {IO; while(~scanf("%d",&n)){ for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) scanf("%lf",&m[i][j]); int q;scanf("%d",&q); for(int p=0;p<q;++p){ scanf("%d%d",&s,&e); dij(); if(dis[e]==0) printf("What a pity! "); else printf("%.3f ",dis[e]); } } }
一般dij例题:畅通工程续
const int maxn=210; int mt[maxn][maxn]; int n,m; int dis[maxn],vis[maxn]; void dijkstra(int src) { for(int i=0;i<n;++i) dis[i]=mt[src][i],vis[i]=0; dis[src]=0; vis[src]=1; int i,k,j; for(i=0;i<n;++i){ int tmp=INF; for(j=0;j<n;++j){ if(!vis[j]&&tmp>=dis[j]){ k=j;tmp=dis[j]; } } if(tmp==INF) break; vis[k]=1; for(j=0;j<n;++j){ if(!vis[j]&&dis[j]>dis[k]+mt[k][j]) dis[j]=dis[k]+mt[k][j]; } } } int main() { while(~scanf("%d%d",&n,&m)){ int x,y,val; for(int i=0;i<n;++i) for(int j=0;j<n;++j) mt[i][j]=INF; for(int i=0;i<m;++i){ scanf("%d%d%d",&x,&y,&val); if(mt[x][y]>val) mt[x][y]=mt[y][x]=val;//重边 } int s,t;scanf("%d%d",&s,&t); dijkstra(s); if(dis[t]==INF) printf("-1 "); else printf("%d ",dis[t]); } return 0; }