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 }

 

posted @ 2013-02-20 17:16  Naix_x  阅读(410)  评论(0编辑  收藏  举报