http://acm.hdu.edu.cn/showproblem.php?pid=3046
题意:
给出矩阵地图和羊和狼的位置,求至少需要建多少栅栏,使得狼不能到达羊。
思路:
狼和羊不能到达,最小割最大流问题。
因为狼和羊都有多只,所以我们加一个超级源点和一个超级汇点,将每只狼与超级源点相连,容量为INF,将每只羊与超级汇点相连,容量为INF。对于地图上的点,每个点都与它上下左右相连,容量设为1。
接下来,我们只需要计算出从超级源点到超级汇点的最大流,因为最小割等于最大流。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<string> 5 #include<vector> 6 #include<queue> 7 using namespace std; 8 9 const int maxn = 210*210; 10 const int INF = 0x3f3f3f3f; 11 12 struct Edge 13 { 14 int from,to, cap, flow; 15 Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f){} 16 }; 17 18 int n, m,t; 19 vector<Edge> edges; 20 vector<int> G[maxn]; 21 int vis[maxn]; 22 int d[maxn]; //从起点到i的距离 23 int cur[maxn]; //当前弧下标 24 int flow; 25 26 void init() 27 { 28 for (int i = 0; i < maxn; i++) 29 G[i].clear(); 30 edges.clear(); 31 } 32 33 void AddEdge(int from, int to, int cap) 34 { 35 edges.push_back(Edge(from, to, cap, 0)); 36 edges.push_back(Edge(to, from, 0, 0)); 37 int m = edges.size(); 38 G[from].push_back(m - 2); 39 G[to].push_back(m - 1); 40 } 41 42 43 int BFS() 44 { 45 memset(vis, 0, sizeof(vis)); 46 queue<int> Q; 47 Q.push(0); 48 d[0] = 0; 49 vis[0] = 1; 50 while (!Q.empty()) 51 { 52 int x = Q.front(); 53 Q.pop(); 54 for (int i = 0; i < G[x].size(); i++) 55 { 56 Edge& e = edges[G[x][i]]; 57 if (!vis[e.to] && e.cap>e.flow) 58 { 59 vis[e.to] = 1; 60 d[e.to] = d[x] + 1; 61 Q.push(e.to); 62 } 63 } 64 } 65 return vis[n*m + 1]; 66 } 67 68 int DFS(int x,int a) 69 { 70 if (x == n*m + 1 || a == 0) return a; 71 int flow = 0, f; 72 for (int& i = cur[x]; i < G[x].size(); i++) 73 { 74 Edge& e = edges[G[x][i]]; 75 if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow)))>0) 76 { 77 e.flow += f; 78 edges[G[x][i] ^ 1].flow -= f; 79 flow += f; 80 a -= f; 81 if (a == 0) break; 82 } 83 } 84 return flow; 85 } 86 87 void Maxflow(int s,int t) 88 { 89 flow = 0; 90 while (BFS()) 91 { 92 memset(cur, 0, sizeof(cur)); 93 flow += DFS(s, INF); 94 } 95 } 96 97 int main() 98 { 99 //freopen("D:\txt.txt", "r", stdin); 100 int kase = 0; 101 int a; 102 while (~scanf("%d%d", &n, &m)) 103 { 104 init(); 105 for (int i = 1; i <= n;i++) 106 for (int j = 1; j <= m; j++) 107 { 108 if (i != 1) 109 AddEdge((i - 1)*m + j, (i-2)*m+j, 1); 110 if (i != n) 111 AddEdge((i - 1)*m + j, i*m + j, 1); 112 if (j != 1) 113 AddEdge((i - 1)*m + j, (i - 1)*m + j - 1, 1); 114 if (j != m) 115 AddEdge((i - 1)*m + j, (i - 1)*m + j + 1, 1); 116 scanf("%d", &a); 117 if (a == 1) 118 AddEdge(0, (i - 1)*m + j, INF); 119 else if (a == 2) 120 AddEdge((i - 1)*m + j, m*n + 1, INF); 121 } 122 Maxflow(0, n*m + 1); 123 printf("Case %d: %d ", ++kase, flow); 124 } 125 }