Description
Input
Output
题目大意:有n个人,n个人之间有一些互相有联系,问最少干掉几个人,S和T之间就没有联系了。输出字典序最小的那几个被干掉人。
思路:问S和T之间少了多少点就不连通,妥妥的最小割,拆点建图。每个点x拆成x、x',连一条边x→x'容量为1(S和T容量为无穷大),若i能联系j,则连边i→j'、j→i',容量为无穷大。最大流就是最少要干掉的人。
然后就是要判断那些点是割点,首先,若x是割点,那么x→x'的流量肯定是满的,其次,我们不能找到另一个点可以替代x(若有a→b→d,a→c→d,c可以替代b,b就不是割点)。也就是说,我们不能再残量网络中找到一条从x到x'的边(嘛因为图的边是无向的),然后退回经过这个点的流,删掉这个点。枚举答案即可。
至于为什么要退回流量,比如S→a→b→c→T,我们找到割点a,如果不退回流量,我们又会找到割点b、c,于是就会妥妥的WA了o(╯□╰)o
ISAP(125MS):
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 using namespace std; 6 7 const int MAXN = 410; 8 const int MAXE = 30010; 9 const int INF = 0x3fff3fff; 10 11 struct SAP { 12 int head[MAXN], dis[MAXN], cur[MAXN], pre[MAXN], gap[MAXN]; 13 int to[MAXE], flow[MAXE], next[MAXE]; 14 int ecnt, n, st, ed; 15 16 void init() { 17 memset(head, 0, sizeof(head)); 18 ecnt = 2; 19 } 20 21 void add_edge(int u, int v, int c) { 22 to[ecnt] = v; flow[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++; 23 to[ecnt] = u; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++; 24 //printf("%d->%d, flow = %d\n", u, v, c); 25 } 26 27 void bfs() { 28 memset(dis, 0x3f, sizeof(dis)); 29 queue<int> que; que.push(ed); 30 dis[ed] = 0; 31 while(!que.empty()) { 32 int u = que.front(); que.pop(); 33 ++gap[dis[u]]; 34 for(int p = head[u]; p; p = next[p]) { 35 int &v = to[p]; 36 if(flow[p ^ 1] && dis[v] > n) { 37 dis[v] = dis[u] + 1; 38 que.push(v); 39 } 40 } 41 } 42 } 43 44 int Max_flow(int ss, int tt, int nn) { 45 st = ss; ed = tt; n = nn; 46 int ans = 0, minFlow = INF, u; 47 for(int i = 0; i <= n; ++i) { 48 cur[i] = head[i]; 49 gap[i] = 0; 50 } 51 u = pre[st] = st; 52 bfs(); 53 while(dis[st] < n) { 54 bool flag = false; 55 for(int &p = cur[u]; p; p = next[p]) { 56 int &v = to[p]; 57 if(flow[p] && dis[u] == dis[v] + 1) { 58 flag = true; 59 minFlow = min(minFlow, flow[p]); 60 pre[v] = u; 61 u = v; 62 if(u == ed) { 63 ans += minFlow; 64 while(u != st) { 65 u = pre[u]; 66 flow[cur[u]] -= minFlow; 67 flow[cur[u] ^ 1] += minFlow; 68 } 69 minFlow = INF; 70 } 71 break; 72 } 73 } 74 if(flag) continue; 75 int minDis = n - 1; 76 for(int p = head[u]; p; p = next[p]) { 77 int &v = to[p]; 78 if(flow[p] && dis[v] < minDis) { 79 minDis = dis[v]; 80 cur[u] = p; 81 } 82 } 83 if(--gap[dis[u]] == 0) break; 84 ++gap[dis[u] = minDis + 1]; 85 u = pre[u]; 86 } 87 return ans; 88 } 89 90 bool vis[MAXN]; 91 92 bool link(int x, int y) { 93 memset(vis, 0, sizeof(vis)); 94 queue<int> que; que.push(x); 95 vis[x] = true; 96 while(!que.empty()) { 97 int u = que.front(); que.pop(); 98 for(int p = head[u]; p; p = next[p]) { 99 int &v = to[p]; 100 if(flow[p] && !vis[v]) { 101 if(v == y) return true; 102 vis[v] = true; 103 que.push(v); 104 } 105 } 106 } 107 return false; 108 } 109 110 void add_flow(int x, int y) { 111 memset(vis, 0, sizeof(vis)); 112 queue<int> que; que.push(x); 113 vis[x] = true; 114 bool flag = false; 115 while(!que.empty()) { 116 int u = que.front(); que.pop(); 117 for(int p = head[u]; p; p = next[p]) { 118 int &v = to[p]; 119 if(flow[p] && !vis[v]) { 120 pre[v] = p; 121 if(v == y) { 122 flag = true; 123 break; 124 } 125 vis[v] = true; 126 que.push(v); 127 } 128 } 129 if(flag) break; 130 } 131 int u = y; 132 while(u != x) { 133 flow[pre[u]] -= 1; 134 flow[pre[u] ^ 1] += 1; 135 u = to[pre[u] ^ 1]; 136 } 137 } 138 } G; 139 140 int mat[MAXN][MAXN]; 141 int edge_id[MAXN]; 142 int n, ss, tt; 143 144 int main() { 145 scanf("%d%d%d", &n, &ss, &tt); 146 G.init(); 147 for(int i = 1; i <= n; ++i) { 148 edge_id[i] = G.ecnt; 149 if(i == ss || i == tt) G.add_edge(i, i + n, INF); 150 else G.add_edge(i, i + n, 1); 151 } 152 for(int i = 1; i <= n; ++i) { 153 for(int j = 1; j <= n; ++j) { 154 scanf("%d", &mat[i][j]); 155 if(i != j && mat[i][j]) G.add_edge(i + n, j, INF); 156 } 157 } 158 if(mat[ss][tt]) { 159 puts("NO ANSWER!"); 160 return 0; 161 } 162 int ans = G.Max_flow(ss, tt + n, n + n); 163 printf("%d\n", ans); 164 if(ans == 0) return 0; 165 bool flag = false; 166 for(int i = 1; i <= n; ++i) { 167 if(G.flow[edge_id[i]] == 0 && !G.link(i, i + n)) { 168 if(flag) printf(" "); 169 flag = true; 170 printf("%d", i); 171 G.flow[edge_id[i]] = G.flow[edge_id[i] ^ 1] = 0; 172 G.add_flow(i, ss); 173 G.add_flow(tt, i + n); 174 } 175 } 176 printf("\n"); 177 }