hdu 1054 Strategic Game 二分图最小点覆盖

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1054

题意:

给出一个无向图,求最小点覆盖。

思路:

用网络流来做设立一个超级源点和一个超级汇点。

每个点拆成i和i'。

从超级源点向点i连一条边,容量为1。

从i’向超级汇点连一条边,容量为1。

从i向i'连一条边,容量为正无穷。

然后求最小割/2。因为拆点拆成了2个。

也可以用二分图匹配来做,也是求出最大匹配然后/2。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 int n, m, s, t;
  4 #define maxn 3500
  5 #define inf 0x3f3f3f3f
  6 struct Edge
  7 {
  8     int from, to, cap, flow;
  9     Edge(int f, int t, int c, int fl)
 10     {
 11         from = f; to = t; cap = c; flow = fl;
 12     }
 13 };
 14 vector <Edge> edges;
 15 vector <int> G[maxn];
 16 int d[maxn], vis[maxn], cur[maxn];
 17 void AddEdge(int from, int to, int cap)
 18 {
 19     edges.push_back(Edge(from, to, cap, 0));
 20     edges.push_back(Edge(to, from, 0, 0));
 21     m = edges.size();
 22     G[from].push_back(m-2);
 23     G[to].push_back(m-1);
 24 }
 25 bool bfs()
 26 {
 27     memset(vis, 0, sizeof(vis));
 28     d[s] = 0;
 29     vis[s] = 1;
 30     queue <int> q;
 31     q.push(s);
 32     while(!q.empty())
 33     {
 34         int x = q.front(); q.pop();
 35         for(int i = 0; i < G[x].size(); i++)
 36         {
 37             Edge &e = edges[G[x][i]];
 38             if(!vis[e.to] && e.cap > e.flow)
 39             {
 40                 d[e.to] = d[x] + 1;
 41                 vis[e.to] = 1;
 42                 q.push(e.to);
 43             }
 44         }
 45     }
 46     return vis[t];
 47 }
 48 int dfs(int x, int a)
 49 {
 50     if(x == t || a == 0) return a;
 51     int flow = 0, f;
 52     for(int &i = cur[x]; i < G[x].size(); i++)
 53     {
 54         Edge &e = edges[G[x][i]];
 55         if(d[e.to] == d[x] + 1 && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0)
 56         {
 57             e.flow += f;
 58             edges[G[x][i]^1].flow -= f;
 59             flow += f;
 60             a -= f;
 61             if(a == 0) break;
 62         }
 63     }
 64     return flow;
 65 }
 66 int maxflow()
 67 {
 68     int flow = 0;
 69     while(bfs())
 70     {
 71         memset(cur, 0, sizeof(cur));
 72         flow += dfs(s, inf);
 73     }
 74     return flow;
 75 }
 76 int N;
 77 int main() 
 78 {
 79  //   freopen("in.txt", "r", stdin);
 80     //freopen("out.txt", "w", stdout);
 81     while(~scanf("%d", &N))
 82     {
 83         edges.clear();
 84         for(int i = 0; i <= 2*N+1; i++) G[i].clear();
 85         char op;
 86         int xh, cnt, u;
 87         s = 0; t = 2*N+1; n = 2*N+2;
 88         for(int i = 1; i <= N; i++) AddEdge(s, i, 1);
 89         for(int i = 1; i <= N; i++) AddEdge(i+N, t, 1);
 90         for(int i = 1; i <= N; i++)
 91         {
 92             scanf("%d", &xh); xh++;
 93             cin>>op; cin>>op;
 94             scanf("%d", &cnt);
 95             cin>>op;
 96             while(cnt--)
 97             {
 98                 scanf("%d", &u); u++;
 99                 AddEdge(xh, u+N, inf);
100                 AddEdge(u, xh+N, inf);
101             }
102         }
103         int flow = maxflow();
104         printf("%d\n", flow/2);
105     }
106     return 0;
107 }

 

posted @ 2016-02-25 22:14  下周LGD该赢了吧  阅读(158)  评论(0编辑  收藏  举报