题目:

  给出一个有向图,求它的最小环。

  有向图的环应至少含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 }
View Code

有向图代码:

 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 }
View Code

 

01-20 22:12