BZOJ 1001:[BeiJing2006]狼抓兔子(最小割)

http://www.lydsy.com/JudgeOnline/problem.php?id=1001

题意:中文。

思路:很明显是最小割,转化为最大流做。一开始看那么多点,但还是试了一下,居然过了。迷。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <queue>
 6 using namespace std;
 7 #define N 1000010
 8 #define INF 0x3f3f3f3f
 9 struct Edge {
10     int v, cap, nxt;
11 } edge[N*6];
12 int head[N], cur[N], pre[N], tot, gap[N], dis[N], S, T;
13 
14 void Add(int u, int v, int cap) {
15     edge[tot] = (Edge) {v, cap, head[u]}; head[u] = tot++;
16     edge[tot] = (Edge) {u, cap, head[v]}; head[v] = tot++;
17 }
18 
19 int BFS() {
20     memset(gap, 0, sizeof(gap));
21     memset(dis, INF, sizeof(dis));
22     queue<int> que;
23     que.push(T);
24     dis[T] = 0; gap[0] = 1;
25     while(!que.empty()) {
26         int u = que.front(); que.pop();
27         for(int i = head[u]; ~i; i = edge[i].nxt) {
28             int v = edge[i].v;
29             if(INF != dis[v]) continue;
30             dis[v] = dis[u] + 1;
31             gap[dis[v]]++;
32             que.push(v);
33         }
34     }
35 }
36 
37 int ISAP(int n) {
38     BFS();
39     memcpy(cur, head, sizeof(cur));
40     int flow, ans = 0, u = pre[S] = S, i, index;
41     while(dis[S] < n) {
42         if(u == T) {
43             flow = INF;
44             for(i = S; i != T; i = edge[cur[i]].v)
45                 if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i;
46             for(i = S; i != T; i = edge[cur[i]].v)
47                 edge[cur[i]].cap -= flow, edge[cur[i]^1].cap += flow;
48             ans += flow; u = index;
49         }
50         for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap > 0 && dis[edge[i].v] == dis[u] - 1) break;
51         if(~i) {
52             cur[u] = i; pre[edge[i].v] = u; u = edge[i].v;
53         } else {
54             if(--gap[dis[u]] == 0) break;
55             int md = n + 1;
56             for(i = head[u]; ~i; i = edge[i].nxt)
57                 if(edge[i].cap > 0 && dis[edge[i].v] < md) md = dis[edge[i].v], cur[u] = i;
58             gap[dis[u] = md + 1]++;
59             u = pre[u];
60         }
61     }
62     return ans;
63 }
64 
65 int main() {
66     int n, m, w;
67     scanf("%d%d", &n, &m);
68     memset(head, -1, sizeof(head));
69     tot = 0;
70     for(int i = 0; i < n; i++)
71         for(int j = 2; j <= m; j++)
72             scanf("%d", &w), Add(j - 1 + i * m, j + i * m, w);
73     for(int i = 1; i < n; i++)
74         for(int j = 1; j <= m; j++)
75             scanf("%d", &w), Add(j + (i - 1) * m, j + i * m, w);
76     for(int i = 1; i < n; i++)
77         for(int j = 2; j <= m; j++)
78             scanf("%d", &w), Add(j - 1 + (i - 1) * m, j + i * m, w);
79     S = 1, T = n * m;
80     printf("%d
", ISAP(T + 1));
81     return 0;
82 }
原文地址:https://www.cnblogs.com/fightfordream/p/6364578.html