题目大意:与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;
}