题目:
给出一个有向图,求它的最小环。
有向图的环应至少含2个顶点,而无向图的一个环至少含3个顶点。
简述:
如果熟悉floyd算法的原理,那么便知道,每次循环都是由最外层的k去松弛点与点之间的距离的,那么对于当前dis[i][j]还未加入k进行松弛,如果有dis[i][j]+map[i][k]+map[k][j]<mincircle,那么此时的i与j的路径和k便形成了一个最小环,然后加入k进行松弛,求下一次能否通过其他点进行松弛而得到最小环,注意求最小环的时候要每更新一个,便求一次路径,不能等到最后才求,,原因是最后的pre数组与当前并不一致。
无向图代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cctype> 4 #include<vector> 5 #include<queue> 6 #include<cstring> 7 #include<algorithm> 8 #define numm ch-48 9 #define pd putchar(' ') 10 #define pn putchar('\n') 11 #define pb push_back 12 #define debug(args...) cout<<#args<<"->"<<args<<endl 13 #define bug cout<<"************" 14 using namespace std; 15 template <typename T> 16 void read(T &res) { 17 bool flag=false;char ch; 18 while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true); 19 for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm); 20 flag&&(res=-res); 21 } 22 template <typename T> 23 void write(T x) { 24 if(x<0) putchar('-'),x=-x; 25 if(x>9) write(x/10); 26 putchar(x%10+'0'); 27 } 28 typedef long long ll; 29 const int maxn=110+10; 30 const int maxm=50010; 31 const int inf=0x3f3f3f3f; 32 const int mod=1e9+7; 33 int a[maxn][maxn],dis[maxn][maxn],pre[maxn][maxn]; 34 vector<int>ans; 35 bool floyed(int n) { ///判最小环 36 int mircle=inf; 37 bool flag=false; 38 for(int k=1;k<=n;k++) { 39 for(int i=1;i<k;i++) 40 for(int j=i+1;j<k;j++) { ///如果环需要至少包含3个点,则i!=j!=k 41 if(dis[i][j]!=inf&&a[i][k]!=inf&&a[k][j]!=inf) {///找到一个,便更新一次 42 if(mircle>dis[i][j]+a[i][k]+a[k][j]) { 43 mircle=dis[i][j]+a[i][k]+a[k][j]; 44 flag=true; 45 ans.clear(); 46 ans.push_back(k); 47 ans.push_back(j); 48 int d=j; 49 do { 50 d=pre[i][d]; 51 ans.push_back(d); 52 }while(d!=i); 53 } 54 } 55 } 56 for(int i=1;i<=n;i++) { ///如果环需要至少包含3个点,则i!=j!=k 57 if(i!=k) 58 for(int j=1;j<=n;j++) { 59 if(i!=j&&j!=k&&dis[i][k]!=inf&&dis[k][j]!=inf) { 60 if(dis[i][j]>dis[i][k]+dis[k][j]) { 61 dis[i][j]=dis[i][k]+dis[k][j]; 62 pre[i][j]=pre[k][j]; ///attention!!! 63 } 64 } 65 } 66 } 67 } 68 return flag; 69 } 70 int main() 71 { 72 int m,n; 73 read(n),read(m); 74 memset(a,inf,sizeof(a)); 75 memset(dis,inf,sizeof(dis)); 76 for(int i=1;i<=n;i++) { 77 for(int j=1;j<=n;j++) 78 pre[i][j]=i; 79 } 80 for(int i=1;i<=m;i++) { 81 int u,v,w; 82 read(u),read(v),read(w); 83 a[u][v]=a[v][u]=dis[u][v]=dis[v][u]=w; 84 } 85 if(floyed(n)) { 86 for(int i=0;i<ans.size();i++) 87 write(ans[i]),pd; 88 pn; 89 } 90 else puts("No solution."); 91 return 0; 92 }
有向图代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cctype> 4 #include<vector> 5 #include<queue> 6 #include<cstring> 7 #include<algorithm> 8 #define numm ch-48 9 #define pd putchar(' ') 10 #define pn putchar('\n') 11 #define pb push_back 12 #define debug(args...) cout<<#args<<"->"<<args<<endl 13 #define bug cout<<"************" 14 using namespace std; 15 template <typename T> 16 void read(T &res) { 17 bool flag=false;char ch; 18 while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true); 19 for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm); 20 flag&&(res=-res); 21 } 22 template <typename T> 23 void write(T x) { 24 if(x<0) putchar('-'),x=-x; 25 if(x>9) write(x/10); 26 putchar(x%10+'0'); 27 } 28 typedef long long ll; 29 const int maxn=2010+10; 30 const int maxm=50010; 31 const int inf=0x3f3f3f3f; 32 const int mod=1e9+7; 33 int a[maxn][maxn],dis[maxn][maxn],pre[maxn][maxn]; 34 int que[maxn+100],cnt; 35 bool floyed(int n) { ///有向图判最小环 36 int mincircle=inf; 37 bool flag=false; 38 for(int k=1;k<=n;k++) { 39 for(int i=1;i<=n;i++) { 40 if(a[k][i]==inf||a[k][i]>mincircle) continue; 41 for(int j=1;j<=n;j++) { 42 if(i==k&&j==k) continue; 43 if(dis[i][j]!=inf&&a[j][k]!=inf) { 44 if(mincircle>dis[i][j]+a[j][k]+a[k][i]) { 45 mincircle=dis[i][j]+a[j][k]+a[k][i]; 46 flag=true; 47 cnt=0; 48 que[++cnt]=k; 49 que[++cnt]=j; 50 int d=j; 51 do { 52 d=pre[i][d]; 53 if(d!=j&&d!=k) 54 que[++cnt]=d; 55 }while(d!=i); 56 57 } 58 } 59 } 60 } 61 for(int i=1;i<=n;i++) { 62 if(dis[i][k]==inf) continue; 63 for(int j=1;j<=n;j++) { 64 if(i==k&&j==k) continue; 65 if(dis[k][j]!=inf) { 66 if(dis[i][j]>dis[i][k]+dis[k][j]) { 67 dis[i][j]=dis[i][k]+dis[k][j]; 68 pre[i][j]=pre[k][j]; 69 } 70 } 71 } 72 } 73 } 74 return flag; 75 } 76 int main() 77 { 78 int m,n; 79 read(n),read(m); 80 memset(a,inf,sizeof(a)); 81 memset(dis,inf,sizeof(dis)); 82 for(int i=1;i<=n;i++) { 83 a[i][i]=dis[i][i]=0; 84 for(int j=1;j<=n;j++) 85 pre[i][j]=i; 86 } 87 for(int i=1;i<=m;i++) { 88 int u,v,w; 89 read(u),read(v),read(w); 90 a[u][v]=dis[u][v]=min(w,a[u][v]); 91 } 92 if(floyed(n)) { 93 for(int i=cnt;i;i--) 94 write(que[i]),pd; 95 pn; 96 } 97 else puts("No solution."); 98 return 0; 99 }