ThievesTime Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 1483 Accepted Submission(s): 665
Problem Description
In the kingdom of Henryy, there are N (2 <= N <= 100) cities, with M (M <= 10000) two-direct ways connecting them.
A group of thieves from abroad plan to steal the metropolitan museum in city H (It has not been demolished). However, the brave, brilliant, bright police in the kingdom have known this plan long before, and they also plan to catch the thieves. The thieves are in the city S at present. The police try to catch them on their way from S to H. Although the thieves might travel this way by more than one group, our excellent police has already gather the statistics that the number of the people needed in city I (1<=I<=N) to arrest the thieves. The police do not want to encounter the thieves in either city S or city H. The police finish the task with the minimum number of people. Do you know the exact number?
Input
The first line contains an integer T (T <= 10), indicating the number of the test cases.
The first line of each test case has four integers: N, the number of the cities; M, the number of the roads; S (1<=S<=N), the label of city S; H (1<=T<=N, S≠H), the label of city H. The second line contains N integers, indicating the number of people needed in each city. The sum of these N integers is less than 10000. Then M lines followed, each containing two integers x and y, indicating that there is a two-direct roads between city x and y. Notices that no road between city S and H. A blank line is followed after each test case.
Output
For each test case, output a single integer in a separate line, indicating the minimum number of people the police used.
Sample Input
Sample Output
|
题意:有N个城市和M条路,已知小偷团伙在城市S,而他们要作案的地点是城市H。现在给出每个城市需要部署的警察人数,要求警察不能在城市S和城市H碰到小偷,问你需要的最少警察数。
思路:最小割求解割点集,拆点成边,跑一次最大流即可。
建图:
1,对于点S和H,建边S -> S+N和 H -> H+N,容量为 无穷大;
2,对于其他点i,建边i -> i+N,容量为1;
3,对于边<u, v>,建边u+N -> v 和 v+N -> u,容量为1。
然后从S到H+N跑一次最大流就ok了。
注意:无向图。
AC代码:
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define MAXN 200+10
#define MAXM 100000
#define INF 0x3f3f3f3f
using namespace std;
struct Edge
{
int from, to, cap, flow, next;
};
Edge edge[MAXM];
int head[MAXN], edgenum;
int dist[MAXN], cur[MAXN];
bool vis[MAXN];
int N, M, S, H;
void init()
{
edgenum = 0;
memset(head, -1, sizeof(head));
}
void addEdge(int u, int v, int w)
{
Edge E1 = {u, v, w, 0, head[u]};
edge[edgenum] = E1;
head[u] = edgenum++;
Edge E2 = {v, u, 0, 0, head[v]};
edge[edgenum] = E2;
head[v] = edgenum++;
}
void getMap()
{
init();
scanf("%d%d%d%d", &N, &M, &S, &H);
int a, b;
for(int i = 1; i <= N; i++)
{
scanf("%d", &a);
if(i == S || i == H)//S 和 H 不能断
addEdge(i, i+N, INF);
else
addEdge(i, i+N, a);
}
for(int i = 0; i < M; i++)
{
scanf("%d%d", &a, &b);
addEdge(a+N, b, INF);//无向图 建双边
addEdge(b+N, a, INF);
}
}
bool BFS(int s, int t)
{
queue<int> Q;
memset(dist, -1, sizeof(dist));
memset(vis, false, sizeof(vis));
dist[s] = 0, vis[s] = true;
Q.push(s);
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(a, E.cap-E.flow), 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;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
getMap();
printf("%d\n", Maxflow(S, H+N));//汇点是H+N
}
return 0;
}