Floyd最短路
时间复杂度n^3
注意一下几个问题
1.44行:由于有重边,所以读入是要确保g[a][b]存的是a->b的‘最短’距离
2.49行:将重边舍去,g[i][i]保证为0;
3.动态规划
状态表示f(k,i,j)—从i到j且经过1-k中的点的最短距离
三重循环–>k在最外层,i和j可以互换
4.64行:不能用==/!=0x3f3f3f3f来判断是否不为/为通路
因为由于存在负权边,所以g[i,j]=min(g[i,j],g[i,k]+g[k,j])时,i到k 和 k到j可能有一条为通路(长度为负),另一条不通(长度正无穷),此时本不应该更新g[i,j]却被更新了,即g[i,j]变小了。
为了避免结果错误,故将判断条件改为>=0x3f3f3f3f/2 ,因为即便由于上述原因导致本不为通路的两点间距离变小,
也不会减少0x3f3f3f3f/2(边长绝对值都不大),所以可以用该判条件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include<iostream> #include<algorithm> #include<cstring> using namespace std;
const int N=210;
int g[N][N];
int main() { memset(g, 0x3f,sizeof(g)); int n,m,t; cin>>n>>m>>t; for(int i=0;i<m;i++) { int a,b,c; cin>>a>>b>>c; g[a][b]=min(g[a][b],c); } for(int i=1;i<=n;i++) g[i][i]=0; for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j)g[i][j]=min(g[i][j],g[i][k]+g[k][j]); for(int i=1;i<=t;i++) { int a,b; cin>>a>>b; if(g[a][b]<=0x3f3f3f3f/2)cout<<g[a][b]<<endl; else puts("impossible"); } return 0; }
|