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 }