您的位置:首页 > 其它

[BZOJ]1001: [BeiJing2006]狼抓兔子

2016-11-24 13:54 232 查看
一道网络流的裸题,但是要注意双向边的建法,我因为太久没打过网络流,建多了很多重复的边,导致TLE。。。。。。
/**************************************************************
Problem: 1001
User: 200815147
Language: C++
Result: Accepted
Time:2060 ms
Memory:106292 kb
****************************************************************/

#include<cstdio>
#include<cstring>
const int Q=1000005;
const int MAX=999999999;
int n,m,st,ed;
int p(int x,int y) {return (x-1)*m+y;}
struct edge
{
int y,d,next,other;
}a[6*Q];
int len=0,last[Q];
void ins(int x,int y,int d)
{
int t1=++len;
a[t1].y=y;a[t1].d=d;a[t1].next=last[x];last[x]=t1;
int t2=++len;
a[t2].y=x;a[t2].d=d;a[t2].next=last[y];last[y]=t2;
a[t1].other=t2;a[t2].other=t1;
}
int h[Q],list[Q];
bool build()
{
memset(h,0,sizeof(h));h[st]=1;
list[1]=st;
int head=1,tail=2;
while(head!=tail)
{
int x=list[head];
for(int i=last[x];i!=-1;i=a[i].next)
{
int y=a[i].y;
if(a[i].d>0 && h[y]==0)
{
h[y]=h[x]+1;
list[tail++]=y;
if(tail==Q-1) tail=1;
}
}
head++;
if(head==Q-1) head=1;
}
if(h[ed]>0) return true;
return false;
}
int mymin(int x,int y) {return x<y?x:y;}
int work(int x,int f)
{
if(x==ed) return f;
int s=0;
for(int i=last[x];i!=-1;i=a[i].next)
{
int y=a[i].y;
if(a[i].d>0 && h[y]==h[x]+1 && s<f)
{
int t=work(y,mymin(f-s,a[i].d));
s+=t;a[a[i].other].d+=t;a[i].d-=t;
}
}
if(s==0) h[x]=0;
return s;
}
int main()
{
memset(last,-1,sizeof(last));
scanf("%d%d",&n,&m);
if(n==1&&m==1) {printf("0");return 0;}
for(int i=1;i<=n;i++)
{
for(int j=1;j<m;j++)
{
int d,num1=(i-1)*m+j;
scanf("%d",&d);
ins(num1,num1+1,d);
//ins(num1+1,num1,d);
}
}
for(int i=1;i<n;i++)
{
for(int j=1;j<=m;j++)
{
int d,num1=(i-1)*m+j,num2=num1+m;
scanf("%d",&d);
ins(num2,num1,d);
//ins(num1,num2,d);
}
}
for(int i=1;i<n;i++)
{
for(int j=1;j<m;j++)
{
int d,num1=(i-1)*m+j,num2=num1+m+1;
scanf("%d",&d);
ins(num2,num1,d);
//ins(num1,num2,d);
}
}
st=1;ed=n*m;
int ans=0;
while(build()==true)
{
//printf("ok\n");
ans+=work(st,MAX);
}
printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: