您的位置:首页 > 其它

BZOJ 1001 狼抓兔子

2016-06-12 11:45 253 查看
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001

现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,
而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:



左上角点为(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只狼,
才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
狼的数量要最小。因为狼还要去找喜羊羊麻烦.

思路:dinic网络流居然过了。。
据说正解是什么对偶图

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
int next[7000005],first[7000005],go[7000005],tot,val[7000005];
int dis[2000005],c[5000005],S,T,n,m,x,ans=0;

int sta(int x,int y){
return (x-1)*m+y;
}
void insert(int x,int y,int z){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
val[tot]=z;

tot++;
go[tot]=x;
next[tot]=first[y];
first[y]=tot;
val[tot]=z;
}
bool bfs(){
int now,i;
memset(dis,-1,sizeof dis);
int h=0,t=1;
c[1]=S;
dis[S]=0;
while (h<t){
h++;
now=c[h];
for (int i=first[now];i;i=next[i]){
int pur=go[i];
if (val[i]&&dis[pur]<0){
c[++t]=pur;
dis[pur]=dis[now]+1;
}
}
}
if (dis[T]==-1) return 0;
return 1;
}
int dfs(int x,int f){
if (x==T) return f;
int w,used=0;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (val[i]&&dis[pur]==dis[x]+1){
w=f-used;
w=dfs(pur,std::min(w,val[i]));
val[i]-=w;
val[i+1]+=w;
used+=w;
if (used==f) return f;
}
}
if (!used) dis[x]=-1;
return used;
}
void dinic(){
while (bfs()) ans+=dfs(1,0x7fffffff);
}
int main(){
scanf("%d%d",&n,&m);
S=1;T=sta(n,m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m-1;j++){
scanf("%d",&x);
insert(sta(i,j),sta(i,j+1),x);
}
for (int i=1;i<=n-1;i++)
for (int j=1;j<=m;j++){
scanf("%d",&x);
insert(sta(i,j),sta(i+1,j),x);
}
for (int i=1;i<=n-1;i++)
for (int j=1;j<=m-1;j++){
scanf("%d",&x);
insert(sta(i,j),sta(i+1,j+1),x);
}
dinic();
printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: