最小割

来源:互联网 发布:淘宝靠谱的苹果二手店 编辑:程序博客网 时间:2024/04/29 20:05

最小割定理:最大流的流量等于最小割对应的边集容量的最小值

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 408struct 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);elseadd_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;}elsemark[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 91 1 1 0 0 0 0 0 01 1 1 1 1 0 0 0 01 1 1 0 1 1 0 0 00 1 0 1 0 0 1 0 00 1 1 0 1 0 1 1 00 0 1 0 0 1 0 1 00 0 0 1 1 0 1 1 10 0 0 0 1 1 1 1 10 0 0 0 0 0 1 1 1*/


0 0