10405: I.Earthquake
Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 19 Solved: 4
[ Submit][ Status][ Web Board]
Description
Wenchuan has had an earthquake that has struck a town.The earthquake has damaged some of the villages so that they are unpassable. Remarkably, none of paths was damaged.
As usual, the town is modeled as a set of P (1 <= P <= 3,000) villages conveniently numbered 1…P which are connected by a set of C (1 <= C <= 20,000) non-directional paths conveniently numbered 1...C. path i connectsvillage Ai and Bi. paths might connect Ai to itself or perhaps might connect twovillages more than once. The town government is located in village 1.
A total of N (1 <= N <= P) villages sequentially contacts the town government via moobile phone with an integer message Vj (2 <= Vj <= P) that indicates that village Vj is undamaged , but the villagers is unable to return to the town governmentfrom village Vj , because they could not find a path that does not go through damaged villages.
After all the villages report in, determine the minimum number of villages that are damaged.
Input
The first line of input gives a single integer, 1 ≤ T ≤ 10, the number of test cases. Then follow, for each test case:
* Line 1: Three space-separated integers: P, C, and N
* Lines 2…C+1: Line i+1 describes path i with two integers: Ai and Bi
* Lines C+2…C+N+1: Line C+1+j contains a single integer: Vj
Output
Output for each test case , a single line with a integer K ,the minimum number of damaged villages.
Sample Input
1
5 5 2
1 2
2 3
3 5
2 4
4 5
45
Sample Output
1
题意:有n个村庄和m条路,当某个村庄被破坏时则不能通过该村庄(道路不会被破坏)。现在知道有p个村庄没有被破坏,但不能连通村庄1。问你该情况下,最小有多少个村庄被破坏。
思路:很裸的最小割。
建图:无向边容量为INF,表示不能阻断。源点S到给定的p个村庄建有向边,容量为INF,表示不能阻断。
给定的p个村庄拆为左右点,容量为INF,表示不能被破坏。其它村庄拆为左点和右点,容量为1。汇点就为1的左点。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef long long LL;
const int MOD = 1e9+7;
const int MAXN = 6000+10;
const int MAXM = 200000;
const int INF = 0x3f3f3f3f;
void add(LL &x, LL y) {x += y; x %= MOD;}
struct Edge{
int from, to, cap, flow, next;
};
Edge edge[MAXM];
int head[MAXN], edgenum;
void init() {CLR(head, -1); edgenum = 0;}
void addEdge(int u, int v, int w)
{
Edge E = {u, v, w, 0, head[u]};
edge[edgenum] = E;
head[u] = edgenum++;
Edge E1 = {v, u, 0, 0, head[v]};
edge[edgenum] = E1;
head[v] = edgenum++;
}
bool vis[MAXN];
int dist[MAXN], cur[MAXN];
bool Bfs(int s, int t)
{
queue<int> Q; Q.push(s);
CLR(vis, false); CLR(dist, -1);
vis[s] = true; dist[0] = 0;
while(!Q.empty())
{
int u = Q.front(); Q.pop();
for(int i = head[u]; i != -1; i = edge[i].next)
{
Edge E = edge[i];
if(!vis[E.to] && E.cap > E.flow)
{
dist[E.to] = dist[u] + 1;
if(E.to == t) return true;
vis[E.to] = true;
Q.push(E.to);
}
}
}
return false;
}
int DFS(int x, int a, int t)
{
if(x == t || a == 0) return a;
int flow = 0, f;
for(int &i = cur[x]; i != -1; i = edge[i].next)
{
Edge &E = edge[i];
if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(E.cap-E.flow, a), t)) > 0)
{
edge[i].flow += f;
edge[i^1].flow -= f;
flow += f;
a -= f;
if(a == 0) break;
}
}
return flow;
}
int Maxflow(int s, int t)
{
int flow = 0;
while(Bfs(s, t))
{
memcpy(cur, head, sizeof(head));
flow += DFS(s, INF, t);
}
return flow;
}
bool use[MAXN];
int main()
{
int t; scanf("%d", &t);
while(t--)
{
int n, m, p; scanf("%d%d%d", &n, &m, &p);
init();
for(int i = 0; i < m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
if(u == v) continue;
addEdge(u+n, v, INF);
addEdge(v+n, u, INF);
}
int S = 0; CLR(use, false);
for(int i = 0; i < p; i++)
{
int v; scanf("%d", &v);
use[v] = true;
addEdge(v, v+n, INF);
addEdge(S, v, INF);
}
for(int i = 1; i <= n; i++) if(!use[i])
addEdge(i, i+n, 1);
printf("%d\n", Maxflow(S, 1));
}
return 0;
}