最小割定理:最大流的流量等于最小割对应的边集容量的最小值
Poj 1815 拆点+枚举暴力 好题 赞
/* * this code is made by LinMeiChen * Problem: poj 1815 * Type of Problem: 最小割 输出割集集合 * Thinking: 拆点+枚举暴力 * Feeling: 又是第一次做好激动 */ #include<iostream> #include<algorithm> #include<stdlib.h> #include<string.h> #include<stdio.h> #include<math.h> #include<string> #include<vector> #include<queue> #include<list> using namespace std; typedef long long lld; typedef unsigned int ud; #define INF_MAX 0x3f3f3f3f #define eatline() char chch;while((chch=getchar())!='\n')continue; #define MemsetMax(a) memset(a,0x3f,sizeof a) #define MemsetZero(a) memset(a,0,sizeof a) #define MemsetMin(a) memset(a,-1,sizeof a) #define MemsetFalse(a) MemsetZero(a) #define PQ priority_queue #define Q queue #define maxn 408 struct Edge { int v, f; int next; }E[maxn*maxn]; int head[maxn], h[maxn]; int level[maxn], stack[maxn]; int ans[maxn], mark[maxn]; int G[maxn][maxn]; int k; int N, S, T; void add_edge(int u, int v, int f) { E[k].v = v; E[k].f = f; E[k].next = head[u]; head[u] = k++; E[k].v = u; E[k].f = 0; E[k].next = head[v]; head[v] = k++; } bool BFS(int s, int t) { memset(level, 0, sizeof level); level[s] = 1; Q<int>q; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); if (u == t) return true; for (int i = head[u]; i != -1; i = E[i].next) { int v = E[i].v; if (!level[v]&& E[i].f > 0) { level[v] = level[u] + 1; q.push(v); } } } return false; } int Dinic(int s, int t) { int maxflow = 0; while (BFS(s, t)) { memcpy(h, head, sizeof h); int top = 0; int u = s; while (true) { if (u == t) { int minflow = INF_MAX, flag=0; for (int i = 0; i < top; i++) { if (minflow>E[stack[i]].f) { minflow = E[stack[i]].f; flag = i; } } for (int i = 0; i < top; i++) { E[stack[i]].f -= minflow; E[stack[i] ^ 1].f += minflow; } top = flag; maxflow += minflow; u = E[stack[top] ^ 1].v; } for (int i = h[u]; i != -1; i = h[u] = E[i].next) { int v = E[i].v; if (level[v] == level[u] + 1 && E[i].f) { break; } } if (h[u] != -1) { stack[top++] = h[u]; u = E[h[u]].v; } else { if (top == 0) break; level[u] = 0; u = E[stack[--top] ^ 1].v; } } } return maxflow; } void MakeGrap() { memset(head, -1, sizeof head); k = 0; for (int i = 1; i <= N;i++) for (int j = 1; j <= N;j++) if (G[i][j]) { add_edge(i + N, j, INF_MAX); add_edge(j + N, i, INF_MAX); } for (int i = 1; i <= N; i++) { if (!mark[i]) add_edge(i, i + N, 1); else add_edge(i, i + N, 0); } } int main() { while (scanf("%d%d%d", &N, &S, &T) != EOF) { for (int i = 1; i <= N; i++) for (int j = 1; j <= N; j++) scanf("%d", &G[i][j]); if (G[S][T]) { printf("NO ANSWER!\n"); continue; } MakeGrap(); int flow = Dinic(S + N, T); printf("%d\n", flow); int cnt = 0; memset(mark, 0, sizeof mark); for (int i = 1; i <= N&&flow; i++) { int f; mark[i] = 1; MakeGrap(); f = Dinic(S + N, T); if (f < flow) { flow--; ans[cnt++] = i; } else mark[i] = 0; } if (cnt == 0) continue; printf("%d", ans[0]); for (int i = 1; i < cnt; i++) printf(" %d", ans[i]); puts(""); } return 0; } /* 9 1 9 1 1 1 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 0 1 1 0 0 0 0 1 0 1 0 0 1 0 0 0 1 1 0 1 0 1 1 0 0 0 1 0 0 1 0 1 0 0 0 0 1 1 0 1 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 1 1 1 */