bzoj1741 [Usaco2005 nov]Asteroids 穿越小行星群
网络流,对于每一个行星,将行星所在行到行星连一条流量为1的边,将行星到其所在列连一条流量为1的边,从源点到所有行连一条流量为1的边,将所有列到汇点都连一条流量为1的边,最大流即为答案。
代码
1 #include<cstdio> 2 #include<algorithm> 3 #define N 1000050 4 #define M 1000050 5 const int inf =0x37373737; 6 using namespace std; 7 int n,m,i,a,b; 8 struct Dinic { 9 int s, t, n, pre[N], cur[N], h[N], level[N], sign, q[N]; 10 int cap[M], to[M], ne[M], flow, e; 11 void liu(int u, int v, int w) { 12 to[e] = v, ne[e] = h[u], cap[e] = w; 13 h[u] = e++; 14 } 15 void link(int u, int v, int w) { 16 liu(u, v, w); 17 liu(v, u, 0); 18 } 19 void init(int n) { 20 for (int i = 0; i <= n; ++i) 21 h[i] = -1; 22 e = 0; 23 } 24 bool bfs() { 25 int L = 0, R = 0; 26 fill(level, level + n, -1); 27 sign = q[R++] = t; 28 level[t] = 0; 29 while (L < R && level[s] == -1) { 30 int c = q[L++]; 31 for (int k = h[c]; ~k; k = ne[k]) { 32 if (cap[k ^ 1] > 0 && level[to[k]] == -1) 33 level[to[k]] = level[c] + 1, q[R++] = to[k]; 34 } 35 } 36 return ~level[s]; 37 } 38 void push() { 39 int pl = inf, p, k; 40 for (p = t; p != s; p = to[k ^ 1]) { 41 k = pre[p]; 42 pl = min(pl, cap[k]); 43 } 44 for (p = t; p != s; p = to[k ^ 1]) { 45 k = pre[p]; 46 cap[k] -= pl; 47 cap[k ^ 1] += pl; 48 if (cap[k] == 0) 49 sign = to[k ^ 1]; 50 } 51 flow += pl; 52 } 53 void dfs(int c) { 54 if (c == t) 55 push(); 56 else { 57 for (int &k = cur[c]; ~k; k = ne[k]) 58 if (cap[k] > 0 && level[to[k]] + 1 == level[c]) { 59 pre[to[k]] = k; 60 dfs(to[k]); 61 if (level[sign] > level[c]) 62 return; 63 sign = t; 64 } 65 level[c] = -1; 66 } 67 } 68 int run(int _s, int _t, int _n) { 69 s = _s, t = _t, n = _n; 70 flow = 0; 71 while (bfs()) { 72 for (int i = 0; i < n; ++i) 73 cur[i] = h[i]; 74 dfs(s); 75 } 76 return flow; 77 } 78 } mf; 79 int main() 80 { 81 scanf("%d%d",&n,&m); 82 mf.init(2*n+m+10); 83 for (i=1;i<=n;i++) 84 mf.link(0,i,1),mf.link(n+i,2*n+m+1,1); 85 for (i=1;i<=m;i++) 86 { 87 scanf("%d%d",&a,&b); 88 mf.link(a,2*n+i,1); 89 mf.link(2*n+i,n+b,1); 90 } 91 printf("%d\n",mf.run(0,2*n+m+1,2*n+m+5)); 92 }