这个题的意思是给你一个无向图, 其中有两个点S, T, 让你去掉图中最小数量的点使得S无法到达T, 不能去掉S或者T, 我们将一个顶点i拆成两个点2*i-1 -> 2*i, 边权为1, 对于一条边i - j, 那么就有2*i -> 2*j-1, 2*j -> 2*i-1, 边权为inf, 然后就是枚举边来求解最小割了, 代码如下:
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; const int inf = 0x3fffffff; const int maxn = 200*2+100; struct Dinic { int n; //n个顶点 struct edge { int from, to, cap; }; vector<int> G[maxn]; vector<edge> e; int level[maxn], iter[maxn]; void init() { for(int i=0; i<=n; i++) G[i].clear(); e.clear(); } void add_edge(int u, int v, int cap) { e.push_back((edge) { u, v, cap }); e.push_back((edge) { v, u, 0 }); int m = e.size(); G[u].push_back(m-2); G[v].push_back(m-1); } void bfs(int s) { memset(level, -1, sizeof(level)); queue<int> que; level[s] = 0; que.push(s); while(!que.empty()) { int u = que.front(); que.pop(); for(int i=0; i<G[u].size(); i++) { edge &te = e[G[u][i]]; if(te.cap>0 && level[te.to]<0) { level[te.to] = level[u] + 1; que.push(te.to); } } } } int dfs(int v, int t, int f) { if(v == t) return f; for(int &i=iter[v]; i<G[v].size(); i++) { edge &tpe = e[G[v][i]]; if(tpe.cap>0 && level[v]<level[tpe.to]) { int d = dfs(tpe.to, t, min(f, tpe.cap)); if(d > 0) { tpe.cap -= d; e[G[v][i]^1].cap += d; return d; } } } return 0; } int max_flow(int s, int t) { int flow = 0; for(;;) { bfs(s); if(level[t]<0) return flow; memset(iter, 0, sizeof(iter)); int f; while((f=dfs(s, t, 0x3fffffff)) > 0) flow += f; } } } di1, di2; int N, S, T; int main() { scanf("%d%d%d", &N, &S, &T); di1.n = 2*N; di1.init(); for(int i=1; i<=N; i++) di1.add_edge(2*i-1, 2*i, 1); bool flog = true; for(int i=1; i<=N&&flog; i++) for(int j=1; j<=N&&flog; j++) { int t; scanf("%d", &t); if(j>i && t==1) { //i -> j di1.add_edge(2*i, 2*j-1, inf); di1.add_edge(2*j, 2*i-1, inf); if((i==S&&j==T)||(j==S&&i==T)) flog=false; } } if(!flog) { printf("NO ANSWER!\n"); return 0; } vector<int> ans; di2 = di1; int f = di2.max_flow(2*S, 2*T-1); for(int i=0; i<N; i++) //N个顶点 { if((i+1)==S || (i+1)==T) continue; di2 = di1; di2.e[2*i].cap = 0; int ff = di2.max_flow(2*S, 2*T-1); if(ff+1 == f) { ans.push_back(i+1); f -= 1; di1.e[2*i].cap = 0; } } printf("%d\n", ans.size()); for(int i=0; i<ans.size(); i++) printf("%d%c", ans[i], i==ans.size()-1?‘\n‘:‘ ‘); return 0; }
时间: 2024-10-13 22:28:16