floyd算法模板HDU1869and求最小环HDU1599
作用:求出图中任意两节点间的最短路径。
时间复杂度:o(n^3);
空间复杂度:o(n^2); mp[i][j]代表从i到j的最短路
算法思想:动态规划
从i到j 经过k节点或者不经过k节点
若经过k 则 mp[i][j]=mp[i][k]+mp[k][j];
else mp[i][j]保持不变
floyd的模板
void floyd() { for(int k=0;k<n;k++) for(int i=0;i<n;i++) for(int j=0;j<n;j++) mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]); }
floyd算法的优点:简单好写
缺点:空间时间复杂度太高,用邻接矩阵很好写,用链式前向星就不太好写了。
以下为HDU1869代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=105,INF=10000000; 4 int mp[maxn][maxn]; 5 int n,m,a,b; 6 void input() 7 { 8 for(int i=0;i<n;i++) 9 for(int j=0;j<n;j++) 10 mp[i][j]=INF; 11 12 while(m--) 13 { 14 cin>>a>>b; 15 mp[a][b]=mp[b][a]=1; 16 } 17 } 18 19 void floyd() 20 { 21 for(int k=0;k<n;k++) 22 for(int i=0;i<n;i++) 23 for(int j=0;j<n;j++) 24 mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]); 25 } 26 27 int main() 28 { 29 while(cin>>n>>m) 30 { 31 bool flag = 0; 32 input(); 33 floyd(); 34 for(int i=0;i<n&&!flag;i++) 35 for(int j=0;j<n&&!flag;j++) 36 if(mp[i][j]>7){ 37 cout<<"No"<<endl; 38 flag=1; 39 break; 40 } 41 if(!flag) cout<<"Yes"<<endl; 42 } 43 44 45 return 0; 46 }
!! 求最小环
环 即从 i 点经过若干点后回到 i 点
经过 j 点和 k点 回到i点的方程是 dis[i][j]+mp[j][k]+mp[k][i];
以下是floyd求最小环的代码
void floyd() { for(int k=1;k<=n;k++) { for(int i=1;i<k;i++) for(int j=i+1;j<k;j++) //成环的序列一定有大小顺序 只要保证i j k 不同就行了 minn=min(minn,dis[i][j]+mp[j][k]+mp[k][i]);//经过j和k点回到起点的最小值 for(int i=1;i<=n;i++) //普通floyd求两点最短路 for(int j=1;j<=n;j++) //在一个循环里 经过k点的dis被更新,下一个循环才会被求最小环使用 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /*** 2 *floyd求最小环 3 *mi =min(mi,dis[i][j]+mp[j][k]+mp[k][i]); 4 *mi 遍历所有边 5 ******/ 6 #include <bits/stdc++.h> 7 using namespace std; 8 const int maxn = 105,INF=100000000; 9 int n,m,a,b,c,minn,mp[maxn][maxn],dis[maxn][maxn]; 10 11 void input() 12 { 13 minn=INF; 14 for(int i=0;i<=n;i++) 15 for(int j=0;j<=n;j++) 16 mp[i][j]=dis[i][j]= INF; 17 while(m--) 18 { 19 scanf("%d%d%d",&a,&b,&c); 20 if(c<mp[a][b]){ 21 mp[a][b]=mp[b][a]=dis[a][b]=dis[b][a]=c; 22 } 23 } 24 } 25 26 void floyd() 27 { 28 for(int k=1;k<=n;k++) 29 { 30 for(int i=1;i<k;i++) 31 for(int j=i+1;j<k;j++) //成环的序列一定有大小顺序 只要保证i j k 不同就行了 32 minn=min(minn,dis[i][j]+mp[j][k]+mp[k][i]);//经过j和k点回到起点的最小值 33 for(int i=1;i<=n;i++) //普通floyd求两点最短路 34 for(int j=1;j<=n;j++) //在一个循环里 经过k点的dis被更新,下一个循环才会被求最小环使用 35 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); 36 } 37 } 38 39 int main() 40 { 41 while(cin>>n>>m) 42 { 43 input(); 44 floyd(); 45 if(minn==INF)cout<<"It's impossible."<<endl; 46 else cout<<minn<<endl; 47 } 48 }
落霞与孤鹜齐飞,秋水共长天一色