题目大意:与http://blog.csdn.net/wyfcyx_forever/article/details/39345281这个相近。只是求的是损坏节点的最小数目。
Sol:
拆点最小割。
S->1 c=INF
提到的点x x'->T c=INF
对于每个点x,为1或是提到的点 x->x' c=INF
对于每个点x,不为1且不是提到的点 x->x' c=1
对于原图每条边x->y x'->y c=INF y'->x c=INF
然后强大的ISAP模板水过。
Code:
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f queue<int> q; #define N 3010 #define M 20010 struct Solver { int head[N << 1], next[(M << 2) + N*2], end[(M << 2) + N*2], flow[(M << 2) + N*2], ind; int gap[N << 1], stack[N << 1], top, cur[N << 1], d[N << 1]; void reset() { ind = top = 0; memset(head, -1, sizeof(head)); } void addedge(int a, int b, int _flow) { int q = ind++; end[q] = b; next[q] = head[a]; head[a] = q; flow[q] = _flow; } void make(int a, int b, int _flow) { //printf("%d %d %d\n", a, b, _flow); addedge(a, b, _flow); addedge(b, a, 0); } void make_db(int a, int b, int _flow) { addedge(a, b, _flow); addedge(b, a, _flow); } void bfs(int T) { memset(gap, 0, sizeof(gap)); memset(d, -1, sizeof(d)); ++gap[d[T] = 0]; q.push(T); int i, j; while(!q.empty()) { i = q.front(); q.pop(); for(j = head[i]; j != -1; j = next[j]) if (d[end[j]] == -1) { ++gap[d[end[j]] = d[i] + 1]; q.push(end[j]); } } } int Maxflow(int S, int T) { bfs(T); memcpy(cur, head, sizeof(cur)); int u = S, res = 0, Min, ins, i; bool find; while(d[S] < T - S + 1) { if (u == T) { Min = INF; for(i = 0; i < top; ++i) if (Min > flow[stack[i]]) Min = flow[stack[i]], ins = i; for(i = 0; i < top; ++i) flow[stack[i]] -= Min, flow[stack[i] ^ 1] += Min; res += Min; u = end[stack[top = ins] ^ 1]; } if (u != T && !gap[d[u] - 1]) break; find = 0; for(int &j = cur[u]; j != -1; j = next[j]) if (flow[j] && d[end[j]] + 1 == d[u]) { ins = j; find = 1; break; } if (find) { stack[top++] = ins; cur[u] = ins; u = end[ins]; } else { Min = T - S + 1; for(int j = head[u]; j != -1; j = next[j]) if (flow[j] && d[end[j]] < Min) { Min = d[end[j]]; cur[u] = j; } if (!--gap[d[u]]) break; ++gap[d[u] = Min + 1]; if (u != S) u = end[stack[--top] ^ 1]; } } return res; } }G; int get[N]; int main() { int n, m, num; scanf("%d%d%d", &n, &m, &num); int a, b, x; register int i, j; G.reset(); G.make(0, 1, INF); for(i = 1; i <= m; ++i) { scanf("%d%d", &a, &b); G.make(a * 2, b * 2 - 1, INF); G.make(b * 2, a * 2 - 1, INF); } while(num--) { scanf("%d", &x); get[x] = 1; } G.make(1, 2, INF); for(i = 2; i <= n; ++i) { if (!get[i]) G.make(2 * i - 1, 2 * i, 1); else G.make(2 * i - 1, 2 * i, INF), G.make(2 * i, 2 * n + 1, INF); } printf("%d", G.Maxflow(0, 2 * n + 1)); return 0; }