BZOJ 1001 Beijing 2006 狼抓兔子 最小割

来源:互联网 发布:中恒软件 编辑:程序博客网 时间:2024/06/05 14:27

题目大意:有一张无向图,描述的是兔子窝的位置和之间的边。现在狼来抓兔子了,兔子慌忙的从(1,1)逃走到(m,n)。每条边上都有能通过最多的兔子数量。狼不想让兔子逃走,每在一条边驻守一只狼就可以避免一个兔子通过。问最少多少狼可以让所有兔子都不能逃走。


思路:建图,按题目中的意思是去掉最小的边使得源到汇不连通,显然的最小割。


CODE:


#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define MAX 7000000#define INF 0x7f7f7f7f#define S 1#define T (m * n)using namespace std;int m,n;int head[MAX],total = 1;int next[MAX],aim[MAX],flow[MAX];int deep[MAX];inline void Add(int x,int y,int f);inline bool BFS();int Dinic(int x,int f);int main(){cin >> m >> n;for(int i = 1;i <= m; ++i)for(int x,j = 1;j <= n - 1; ++j) {scanf("%d",&x);Add((i - 1) * n + j,(i - 1) * n + j + 1,x);Add((i - 1) * n + j + 1,(i - 1) * n + j,x);}for(int i = 1;i <= m - 1; ++i)for(int x,j = 1;j <= n; ++j) {scanf("%d",&x);Add((i - 1) * n + j,i * n + j,x);Add(i * n + j,(i - 1) * n + j,x);}for(int i = 1;i <= m - 1; ++i)for(int x,j = 1;j <= n - 1; ++j) {scanf("%d",&x);Add((i - 1) * n + j,i * n + j + 1,x);Add(i * n + j + 1,(i - 1) * n + j,x);}int temp,max_flow = 0;while(BFS())while(temp = Dinic(S,INF),temp)max_flow += temp;cout << max_flow;return 0;}inline void Add(int x,int y,int f){next[++total] = head[x];aim[total] = y;flow[total] = f;head[x] = total;}inline bool BFS(){static queue<int> q;while(!q.empty())q.pop();memset(deep,0,sizeof(deep));q.push(S);deep[S] = 1;while(!q.empty()) {int x = q.front(); q.pop();for(int i = head[x];i;i = next[i]) if(!deep[aim[i]] && flow[i]) {deep[aim[i]] = deep[x] + 1;q.push(aim[i]);if(aim[i] == T)return true;}}return false;}int Dinic(int x,int f){int temp = f;if(x == T)return f;for(int i = head[x];i;i = next[i])if(deep[aim[i]] == deep[x] + 1 && flow[i] && temp) {int away = Dinic(aim[i],min(flow[i],temp));if(!away)deep[aim[i]] = 0;flow[i] -= away;flow[i^1] += away;temp -= away;}return f - temp;}


0 0
原创粉丝点击