最小割
参考
网络流建模汇总
教程:最大流-最小割定理
http://blog.csdn.net/lenleaves/article/details/7887217
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <vector> #include <sstream> using namespace std; #define ll long long const int MAXN = 505; const int MAXM = 400010; const int INF = 0x3f3f3f3f; struct Edge{ int from,to,next,cap,flow; }edge[MAXM]; int tol; int head[MAXN<<1]; int gap[MAXN<<1],dep[MAXN<<1],cur[MAXN<<1]; void init(){ tol = 0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w,int rw = 0){ edge[tol].from = u, edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].from = v, edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++; } int Q[MAXN]; void BFS(int start,int end) { memset(dep,-1,sizeof(dep)); memset(gap,0,sizeof(gap)); gap[0] = 1; int front = 0, rear = 0; dep[end] = 0; Q[rear++] = end; while(front != rear){ int u = Q[front++]; for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].to; if(dep[v] != -1)continue; Q[rear++] = v; dep[v] = dep[u] + 1; gap[dep[v]]++; } } } int S[MAXN]; int isap(int start,int end,int N){ BFS(start,end); memcpy(cur,head,sizeof(head)); int top = 0; int u = start; int ans = 0; while(dep[start] < N){ if(u == end){ int Min = INF; int inser; for(int i = 0;i < top;i++) if(Min > edge[S[i]].cap - edge[S[i]].flow){ Min = edge[S[i]].cap - edge[S[i]].flow; inser = i; } for(int i = 0;i < top;i++){ edge[S[i]].flow += Min; edge[S[i]^1].flow -= Min; } ans += Min; top = inser; u = edge[S[top]^1].to; continue; } bool flag = false; int v; for(int i = cur[u]; i != -1; i = edge[i].next){ v = edge[i].to; if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]){ flag = true; cur[u] = i; break; } } if(flag){ S[top++] = cur[u]; u = v; continue; } int Min = N; for(int i = head[u]; i != -1; i = edge[i].next) if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min){ Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if(!gap[dep[u]])return ans; dep[u] = Min + 1; gap[dep[u]]++; if(u != start)u = edge[S[--top]^1].to; } return ans; } int s, en, n, m, a, t; int g[205][205]; bool del[205]; vector<int> vec; void build(){ init(); for(int i = 1; i <= n; i++){ if(del[i])continue; if(i != s && i != t)addedge(i, i+n, 1); for(int j = 1; j <= n; j++){ if(del[j])continue; if(i == j )continue; if(!g[i][j])continue; if(s == i)addedge(s, j, INF); else if(t == i)addedge(j+n, t, INF); else if(j != s && j != t)addedge(i+n, j, INF); } } } int main(){ while(~scanf("%d%d%d", &n, &s, &t)) { vec.clear(); for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ scanf("%d",&g[i][j]); } } if(g[s][t]){ puts("NO ANSWER!"); continue; } memset(del,false,sizeof(del)); build(); int ans = isap(s,t,2*n); printf("%d\n",ans); if(!ans)continue; int temp = ans; for(int i = 1; i <= n; i++){ if(i == s || i == t)continue; del[i] = true; build(); int k = isap(s,t,2*n); if(k < temp){ vec.push_back(i); temp = k; } else del[i] = false; } int sz = vec.size(); for(int i = 0; i < sz-1; i++){ printf("%d ",vec[i]); } printf("%d\n",vec[sz-1]); } return 0; }