POJ 1966 <点连通度>

题意:

给出点和边的个数n, m

给出相连点的边..形如(a, b)

求最少删去多少个点可以使存在不相邻的两个点不连通..

思路:

拆点+求最大流..

①. 构造一个容量网络N

②. 原图中的每个顶点变成网络N中的两个顶点v' 和 v'', 顶点v' 和 v''之间存在一条弧容量为1<确保这个点只可以路过一次..>

③. 原图G中的每条边e(u, v), 在N中都有对应弧为e'<u'', v'> 和 e''<u', v''>, e' 和 e'' 容量为INF<表示可以在任意两个点之间连线>

④. 遍历两两不相邻的点求最大流的最小值..

Tips:

※. 用EK算法可以在POJ上ac~但是学校OJ就会wa..因为POJ只要固定一个点就好~而学校的需要遍历两两不相邻的点..感觉是POJ的数据弱了..

※. 最大流用SAP算法能快点..

※. 源点为u'' 汇点为v'

Code:

POJ ac代码
 1 #include <stdio.h>
 2 #include <cstring>
 3 #include <queue>
 4 #define INF 0x1f1f1f1f
 5 #define clr(x) memset(x, 0, sizeof(x))
 6 using namespace std;
 7 
 8 int cap[155][155], flow[155][155];
 9 int p[155], a[155];
10 int f, n, m;
11 
12 void EK(int s, int t)
13 {
14     queue<int> q;
15     memset(flow, 0, sizeof(flow));
16     memset(a, 0, sizeof(a));
17     memset(p, 0, sizeof(p));
18     f = 0;
19     while(1)
20     {
21         memset(a, 0, sizeof(a));
22         a[s] = INF;
23         q.push(s);
24         while(!q.empty())
25         {
26             int u = q.front();
27             q.pop();
28             for(int v = 1; v <= 2*n; ++v)
29             if(!a[v] && cap[u][v] > flow[u][v])
30             {
31                 p[v] = u;
32                 q.push(v);
33                 a[v] = a[u] < cap[u][v] - flow[u][v]? a[u]:cap[u][v] - flow[u][v];
34             }
35         }
36         if(a[t] == 0) break;
37         for(int u = t; u != s; u = p[u])
38         {
39             flow[p[u]][u] += a[t];
40             flow[u][p[u]] -= a[t];
41         }
42         f += a[t];
43     }
44 }
45 
46 int main()
47 {
48     int i, j, k;
49     int a, b;
50     while(scanf("%d %d", &n, &m) != EOF)
51     {
52         if(n == 0){
53             puts("0");
54             continue;
55         }
56         clr(cap);
57 
58         for(i = 1; i <= n; ++i)
59         cap[i][i+n] = 1;
60 
61         while(m--){
62             scanf(" (%d,%d)", &a, &b);
63             cap[a+1+n][b+1] = cap[b+1+n][a+1] = INF;
64         }
65         int ans = INF;
66 
67         for(i = 2; i <= n; ++i){
68             EK(n+1, i);
69             if(f < ans) ans = f;
70         }
71 
72         if(ans == INF)
73             printf("%d\n", n);
74         else
75             printf("%d\n", ans);
76     }
77 
78     return 0;
79 }

 

 

posted @ 2012-08-26 11:56  Griselda.  阅读(533)  评论(0编辑  收藏  举报