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 }