标签:
Cops and Thieves
Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
Description
Input
Output
Sample Input
input | output |
---|---|
10 5 5 1 5 1 6 6 11 1 1 2 1 3 2 4 3 4 4 5 |
NO |
10 5 5 1 5 1 4 4 11 1 1 2 1 3 2 4 3 4 4 5 |
YES |
题意:
有一群小偷,从F点要去S点偷东西。现在有N个地点(包括F和S在内),M条路。
总共有K个警察,已知每个地点需要把守的警察数量ai,每个地点必须要那么多警察才能防止小偷。(F和S点不需要)
问是否这K个人足够阻止小偷。
思路:
由于权值在点上,所以需要拆点。
把第i和地点拆成i和i",从i到i"连接一条容量为ai的边。
设F”为源点,S为汇点。
把给出的每条边u->v拆成两条边。
分别是u"->v和v"->u,容量为正无穷,然后求最大流。
如果最大流<=K则可以防守,如果>K则不行。
要注意的是如果S和F相等,那么也不行。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define maxn 210 4 int K, N, M, S, F; 5 const int inf = 0x3f3f3f3f; 6 struct Edge 7 { 8 int from, to, cap, flow; 9 Edge(int f, int t, int c, int fl) 10 { 11 from = f; to = t; cap = c; flow = fl; 12 } 13 }; 14 vector <Edge> edges; 15 vector <int> G[maxn]; 16 int n, m, s, t; 17 int d[maxn], cur[maxn], vis[maxn]; 18 void AddEdge(int from, int to, int cap) 19 { 20 edges.push_back(Edge(from, to, cap, 0)); 21 edges.push_back(Edge(to, from, 0, 0)); 22 m = edges.size(); 23 G[from].push_back(m-2); 24 G[to].push_back(m-1); 25 } 26 bool bfs() 27 { 28 memset(vis, 0, sizeof(vis)); 29 d[s] = 0; 30 vis[s] = 1; 31 queue <int> q; 32 q.push(s); 33 while(!q.empty()) 34 { 35 int u = q.front(); q.pop(); 36 for(int i = 0; i < G[u].size(); i++) 37 { 38 Edge &e = edges[G[u][i]]; 39 if(!vis[e.to] && e.cap > e.flow) 40 { 41 vis[e.to] = 1; 42 d[e.to] = d[u]+1; 43 q.push(e.to); 44 } 45 } 46 } 47 return vis[t]; 48 } 49 int dfs(int x, int a) 50 { 51 if(x == t || a == 0) return a; 52 int flow = 0, f; 53 for(int &i = cur[x]; i < G[x].size(); i++) 54 { 55 Edge &e = edges[G[x][i]]; 56 if(d[x]+1 == d[e.to] && (f = dfs(e.to, min(e.cap-e.flow, a))) > 0) 57 { 58 e.flow += f; 59 edges[G[x][i]^1].flow -= f; 60 flow += f; 61 a -= f; 62 if(a == 0) break; 63 } 64 } 65 return flow; 66 } 67 int MaxFlow() 68 { 69 int flow = 0; 70 while(bfs()) 71 { 72 memset(cur, 0, sizeof(cur)); 73 flow += dfs(s, inf); 74 } 75 return flow; 76 } 77 int main() 78 { 79 while(~scanf("%d", &K)) 80 { 81 scanf("%d%d%d%d", &N, &M, &S, &F); 82 s = F+N; t = S; 83 edges.clear(); 84 for(int i = 1; i <= 2*N; i++) G[i].clear(); 85 86 for(int i = 1; i <= N; i++) 87 { 88 int temp; scanf("%d", &temp); 89 AddEdge(i, N+i, temp); 90 } 91 for(int i = 1; i <= M; i++) 92 { 93 int a, b; 94 scanf("%d%d", &a, &b); 95 AddEdge(a+N, b, inf); 96 AddEdge(b+N, a, inf); 97 } 98 int flow = MaxFlow(); 99 100 if(flow <= K && S != F) printf("YES\n"); 101 else printf("NO\n"); 102 } 103 return 0; 104 }
URAL 1277 Cops and Thieves 最小割 无向图点带权点连通度
标签:
原文地址:http://www.cnblogs.com/titicia/p/4857075.html