USACO 4.1 Fence Loops(无向图中的最小环)

这个算是一个模版题,不过以前没见过。。。我冥思苦想,想爆搜,却知从何搜起,然后突然想到以前做过一个最小环的,关于某一个点的最小环两遍spfa,搞定。然后我啪啪开写,先自己把数据转化为点,然后离散一下。。。写了老长,还选择比较好写的floyd,样例过不了,意识到发现这样写不对啊。。。

从网上找到了做法。。

1:朴素的求最小环的方法做E遍Dijkstra,枚举每条边e(i,j),删去边e(i,j)之后,求i到j的最短路经,然后再加上该边求最小值便得到的了最小环,时间复杂度为O(E*(N^2))。

2:改进的floyd算法,求出任意两点之间的最短路的同时,求出最小环。

我用的是后者,因为图都建好了。。。不能白写了啊。。。证明详细,还是去搜网上的资料把。

  1 /*

  2     ID: cuizhe

  3     LANG: C++

  4     TASK: fence6

  5 */

  6 #include <iostream>

  7 #include <cstdio>

  8 #include <cstring>

  9 #include <cmath>

 10 #include <algorithm>

 11 #include <map>

 12 #include <string>

 13 #include <vector>

 14 using namespace std;

 15 #define N 10000000

 16 int o[301];

 17 int dp[201][201],g[201][201];

 18 struct point

 19 {

 20     int x,y,dis;

 21     int nl,nr;

 22     int L[9],R[9];

 23 } p[101];

 24 int pfind(int x,int key)

 25 {

 26     int i;

 27     for(i = 1; i <= p[key].nl; i ++)

 28     {

 29         if(p[key].L[i] == x)

 30             return p[key].x;

 31     }

 32     for(i = 1; i <= p[key].nr; i ++)

 33     {

 34         if(p[key].R[i] == x)

 35             return p[key].y;

 36     }

 37     return 200;

 38 }

 39 int  build(int n)//建图

 40 {

 41     int i,j,r,c,num;

 42     for(i = 1; i <= n; i ++)

 43     {

 44         o[p[i].x] = 1;

 45         o[p[i].y] = 1;

 46     }

 47     num = 1;

 48     for(i = 1; i <= 2*n; i ++)

 49     {

 50         if(o[i])

 51             o[i] = num ++;

 52     }

 53     for(i = 1; i <= num-1; i ++)

 54     {

 55         for(j = 1; j <= num-1; j ++)

 56         {

 57             g[i][j] = dp[i][j] = N;

 58         }

 59         g[i][j] = dp[i][i] = 0;

 60     }

 61     for(i = 1; i <= n; i ++)

 62     {

 63         if(o[p[i].x] > o[p[i].y])

 64         {

 65             r = o[p[i].x];

 66             c = o[p[i].y];

 67         }

 68         else

 69         {

 70             c = o[p[i].x];

 71             r = o[p[i].y];

 72         }

 73         g[r][c] = dp[r][c] = min(dp[r][c],p[i].dis);

 74         g[c][r] = dp[c][r] = min(dp[c][r],p[i].dis);

 75     }

 76     return num-1;

 77 }

 78 int main()

 79 {

 80     int i,j,n,num,k,minz;

 81     freopen("fence6.in","r",stdin);

 82     freopen("fence6.out","w",stdout);

 83     scanf("%d",&n);

 84     for(i = 1; i <= n; i ++)

 85     {

 86         p[i].x = 2*i-1;

 87         p[i].y = 2*i;

 88     }

 89     for(i = 1; i <= n; i ++)

 90     {

 91         scanf("%d",&num);

 92         scanf("%d%d%d",&p[num].dis,&p[num].nl,&p[num].nr);

 93         for(j = 1; j <= p[num].nl; j ++)

 94             scanf("%d",&p[num].L[j]);

 95         for(j = 1; j <= p[num].nr; j ++)

 96             scanf("%d",&p[num].R[j]);

 97     }

 98     for(i = 1; i <= n; i ++)

 99     {

100         for(j = 1; j <= p[i].nl; j ++)

101         {

102             p[i].x = min(p[i].x,pfind(i,p[i].L[j]));

103         }

104         for(j = 1; j <= p[num].nr; j ++)

105         {

106             p[i].y = min(p[i].y,pfind(i,p[i].R[j]));

107         }

108     }

109     n = build(n);

110     minz = N;

111     for(i = 1; i <= n; i ++)//求最小环

112     {

113         for(j = 1; j <= i-1; j ++)

114             for(k = j+1; k <= i-1; k ++)

115                 minz = min(minz,dp[j][k] + g[j][i] + g[i][k]);

116         for(j = 1; j <= n; j ++)

117             for(k = 1; k <= n; k ++)

118                 dp[j][k] = min(dp[j][k],dp[j][i]+dp[i][k]);

119     }

120     printf("%d\n",minz);

121     return 0;

122 }

 

你可能感兴趣的:(USACO)