Thieves
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 1145 Accepted Submission(s): 514
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?
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.
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
1 5 5 1 5 1 6 6 11 1 1 2 1 3 2 4 3 4 4 5
Sample Output
11题意:有n个城市,小偷要从城市S到城市H,警察要在小偷在S到H的路上把小偷逮捕。给出每个城市需要的警察数目和m条城市之间的道路,道路是无向的。问要把小偷逮捕,至少需要多少个警察。思路:求至少需要多少个警察,即求哪个城市是必须有警察的,转化为求图中S到H的割。最小割即为所求。构图如下:将每个城市拆为两个点k和k',k和k'之间连一条边,容量为城市需要的警察数,表示选择这个城市时付出的代价。对于每条路径a b,连边a'->b和b'->a,容量均为INF,表示不能割这条边。然后虚拟一个源点,连向S,容量为INF,虚拟一个汇点,H'连向汇点,容量为INF。最后求最大流AC代码:#include <iostream> #include <cmath> #include <cstdlib> #include <cstring> #include <cstdio> #include <queue> #include <ctime> #include <algorithm> #define ll __int64 using namespace std; const int INF = 1000000000; const int maxn = 205; struct Edge { int u, v, cap, flow, next; } et[maxn * maxn * 2]; int low[maxn], cnt[maxn], dis[maxn], cur[maxn], pre[maxn], eh[maxn]; int s, t, n, m, num, S, H; void init() { memset(eh, -1, sizeof(eh)); num = 0; } void add(int u, int v, int cap, int flow) { Edge e = {u, v, cap, flow, eh[u]}; et[num] = e; eh[u] = num++; } void addedge(int u, int v, int cap) { add(u, v, cap, 0); add(v, u, 0, 0); } int isap(int s, int t, int nv) { int u, v, now, flow = 0; memset(cnt, 0, sizeof(cnt)); memset(dis, 0, sizeof(dis)); memset(low, 0, sizeof(low)); for(u = 0; u <= nv; u++) cur[u] = eh[u]; low[s] = INF, cnt[0] = nv, u =s; while(dis[s] < nv) { for(now = cur[u]; now != -1; now = et[now].next) if(et[now].cap - et[now].flow && dis[u] == dis[v = et[now].v] + 1) break; if(now != -1) { cur[u] = pre[v] = now; low[v] = min(et[now].cap - et[now].flow, low[u]); u = v; if(u == t) { for(; u != s; u = et[pre[u]].u) { et[pre[u]].flow += low[t]; et[pre[u]^1].flow -= low[t]; } flow += low[t]; low[s] = INF; } } else { if(--cnt[dis[u]] == 0) break; dis[u] = nv, cur[u] = eh[u]; for(now = eh[u]; now != -1; now = et[now].next) if(et[now].cap - et[now].flow && dis[u] > dis[et[now].v] + 1) dis[u] = dis[et[now].v] + 1; cnt[dis[u]]++; if(u != s) u = et[pre[u]].u; } } return flow; } int main() { int tt, a, b; scanf("%d", &tt); while(tt--) { init(); scanf("%d%d%d%d", &n, &m, &S, &H); addedge(S, S + n, INF); addedge(H, H + n, INF); s = 0; t = 2 * n + 1; addedge(s, S, INF); addedge(H + n, t, INF); for(int i = 1; i <= n; i++) { scanf("%d", &a); if(i == s || i == t) continue; addedge(i, i + n, a); } while(m--) { scanf("%d%d", &a, &b); addedge(a + n, b, INF); addedge(b + n, a, INF); } printf("%d\n", isap(s, t, t + 1)); } return 0; }