首页 > 代码库 > bzoj 1001 [BeiJing2006]狼抓兔子
bzoj 1001 [BeiJing2006]狼抓兔子
1001: [BeiJing2006]狼抓兔子
Description
现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路
1:(x,y)<==>(x+1,y)
2:(x,y)<==>(x,y+1)
3:(x,y)<==>(x+1,y+1)
道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的狼的数量要最小。因为狼还要去找喜羊羊麻烦.
Input
第一行为N,M.表示网格的大小,N,M均小于等于1000.
接下来分三部分
第一部分共N行,每行M-1个数,表示横向道路的权值.
第二部分共N-1行,每行M个数,表示纵向道路的权值.
第三部分共N-1行,每行M-1个数,表示斜向道路的权值.
输入文件保证不超过10M
Output
输出一个整数,表示参与伏击的狼的最小数量.
Sample Input
3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
Sample Output
14
用来验证模板的题目。看似只有1000,但其实规模很大,让我多次JIJI。
最大流=最小割,本人蒟蒻,只会DINIC。什么ISAP统统不会。DINIC
1 /************************************************************** 2 Problem: 1001 3 User: Doggu 4 Language: C++ 5 Result: Accepted 6 Time:2032 ms 7 Memory:122924 kb 8 ****************************************************************/ 9 10 #include <cstdio>11 #include <algorithm>12 #include <cstring>13 #include <queue>14 #define pos(x,y) ((x-1)*m+y)15 16 const int M = 7000000 + 10;17 const int N = 1000000 + 10;18 struct Edge {int v, upre, cap, flow;}g[M];19 int head[N], ne = 0;20 inline void adde(int u,int v,int cap) {21 //printf("ADDE:%d %d %d\n",u,v,cap);22 g[ne]=(Edge){v,head[u],cap,0};head[u]=ne++;23 g[ne]=(Edge){u,head[v],cap,0};head[v]=ne++;24 }25 26 int n, m, u, v, cap, s, t;27 struct DINIC {28 int d[N];29 bool vis[N];30 std::queue<int> q;31 bool BFS() {//建立层次图 32 memset(vis, 0, sizeof(vis));33 while(!q.empty()) q.pop();34 vis[s] = 1;d[s] = 0;q.push(s);35 while(!q.empty()) {36 int u = q.front();q.pop();37 for( int i = head[u]; i != -1; i = g[i].upre ) {38 int v = g[i].v;39 if(!vis[v] && g[i].cap>g[i].flow) vis[v] = 1, d[v] = d[u] + 1, q.push(v);40 }41 }42 return vis[t];43 } 44 45 int cur[N];46 int DFS(int u,int a) {//找增广路 47 if(u == t||a == 0) return a;//注意是return a 48 int f, flow = 0;49 for( int& i = cur[u]; i != -1; i = g[i].upre ) {//不要忘了加cur 50 int v = g[i].v;51 if(d[u] + 1 == d[v] && (f=DFS(v,std::min(a,g[i].cap-g[i].flow)))>0) {52 g[i].flow+=f;g[i^1].flow-=f;flow+=f;a-=f;//加加减减 53 if(a==0) break;54 }55 }56 return flow;57 }58 void maxflow() {59 int flow = 0;60 while(BFS()) {61 memcpy(cur,head,sizeof(head));//每一次清零 62 flow += DFS(s,0x3f3f3f3f);63 }64 printf("%d\n",flow);65 }66 }dinic;67 int main() {68 memset(head,-1,sizeof(head));69 scanf("%d%d",&n,&m);70 for( int x = 1; x <= n; x++ ) for( int y = 1; y < m; y++ ) {71 scanf("%d",&cap);72 adde(pos(x,y),pos(x,y+1),cap);73 //adde(pos(x,y+1),pos(x,y),cap);74 }75 for( int x = 1; x < n; x++ ) for( int y = 1; y <= m; y++ ) {76 scanf("%d",&cap);77 adde(pos(x,y),pos(x+1,y),cap);78 //adde(pos(x+1,y),pos(x,y),cap);79 }80 for( int x = 1; x < n; x++ ) for( int y = 1; y < m; y++ ) {81 scanf("%d",&cap);82 adde(pos(x,y),pos(x+1,y+1),cap);83 //adde(pos(x+1,y+1),pos(x,y),cap);84 }85 s=pos(1,1);t=pos(n,m);86 dinic.maxflow();87 return 0;88 }89
bzoj 1001 [BeiJing2006]狼抓兔子
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。