您的位置:首页 > 其它

joj 2724: Hua Rong Dao 最小割

2011-09-20 13:51 197 查看
2724 Hua Rong Dao

I guess you are fond of playing San Guo Sha, right? So here comes a problem of San Guo. It‟s

a famous story – “Hua Rong Dao”.

In order to help Cao Cao to escape, the soldiers of Cao Cao have been divided into several

parts, and Cao Cao is in one of these part. Now they are all in a rectangle area which can be

divided into many squares of the equal size. Once the soldiers get out of this area, they escape

successfully.

Because Liu Bei and Sun Quan don't know exactly which part Cao Cao is in, they decided to

catch all Cao Cao's soldiers.

In this area, some squares are lawns that can be passed, while some others are Marshes that

can't be passed. Liu Bei and Sun Quan decide to set fire on lawns to those squares that cannot

be passed. Owing to some reasons, setting fire on different squares needs different length of

time. And they can only set fire on one square at the same time. Now, Cao Cao and all his

soldiers are having rest and you can assume that they won't move. Liu Bei and SunQuan

want to know how much time they need at least to set fire to make Cao Cao and all his

soldiers can't escape in whatever way when they want to move. Can you help them?

Input

The first line in the input file is a single integer: T (1 ≤ T ≤ 10), representing the number of test

cases. For each test case, in the first line there are two integers: r and c (1 ≤ r, c ≤ 30) - the

height and length of the area. Then there are r lines, in each line there are c integers. The j-th

integer in the i-th line is m . Each of these integers describes a square: if t is positive, then the

ij ij

square is a lawn and it needs mij unit of time to set fire on it; if mij is 0, it means some soldiers

of Cao Cao are having rest in this square; if mij is -1, means the square can't be passed.

When Cao Cao and his soldiers move, they can only move to a square that share an edge with

the square they are in just now. All positive integers in the input file are smaller or equal to

100.

Output

For each test case, output a single integer, means the number of unit of time Liu Bei and Sun

Quan need to set fire so that Cao Cao and his soldiers can't get escape.

It is guaranted that the answer is exists.

Sample Input

1

4 3

1 2 1

1 10 1

1 0 -1

1 1 1

Sample Output

6

//

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

const int N=2010;

const int M=550000;//500000 不够

const int inf=(1<<28);

int head
;

struct Edge

{

int u,v,next,w;

} edge[M];

int cnt,n,s,t;//n从0开始 0->n-1

void addedge(int u,int v,int w)

{

edge[cnt].u=u;

edge[cnt].v=v;

edge[cnt].w=w;

edge[cnt].next=head[u];

head[u]=cnt++;

edge[cnt].u=v;

edge[cnt].v=u;

edge[cnt].w=0;

edge[cnt].next=head[v];

head[v]=cnt++;

}

int sap()

{

int pre
,cur
,dis
,gap
;

int flow=0,aug=inf,u;

bool flag;

for(int i=0; i<n; i++)

{

cur[i]=head[i];

gap[i]=dis[i]=0;

}

gap[s]=n;

u=pre[s]=s;

while(dis[s]<n)

{

flag=0;

for(int &j=cur[u]; j!=-1; j=edge[j].next)

{

int v=edge[j].v;

if(edge[j].w>0&&dis[u]==dis[v]+1)

{

flag=1;

if(edge[j].w<aug) aug=edge[j].w;

pre[v]=u;

u=v;

if(u==t)

{

flow+=aug;

while(u!=s)

{

u=pre[u];

edge[cur[u]].w-=aug;

edge[cur[u]^1].w+=aug;

}

aug=inf;

}

break;

}

}

if(flag) continue;

int mindis=n;

for(int j=head[u]; j!=-1; j=edge[j].next)

{

int v=edge[j].v;

if(edge[j].w>0&&dis[v]<mindis)

{

mindis=dis[v];

cur[u]=j;

}

}

if((--gap[dis[u]])==0)

break;

gap[dis[u]=mindis+1]++;

u=pre[u];

}

return flow;

}

//初始化 cnt=0;memset(head,-1,sizeof(head));

int xx[4]={0,0,1,-1};

int yy[4]={1,-1,0,0};

int a[50][50];

//最小割+拆点

int main()

{

int ci;scanf("%d",&ci);

while(ci--)

{

int m,p;scanf("%d%d",&m,&p);

int num=m*p;

for(int i=1;i<=m;i++) for(int j=1;j<=p;j++) scanf("%d",&a[i][j]);

n=num*2+2;

s=0,t=n-1;

cnt=0;

memset(head,-1,sizeof(head));

for(int i=1;i<=m;i++)

{

for(int j=1;j<=p;j++)

{

int pos=(i-1)*p+j;

if(a[i][j]==-1)

{

}

else if(a[i][j]>0)

{

addedge(pos,pos+num,a[i][j]);

}

else

{

addedge(s,pos,inf);

addedge(pos,pos+num,inf);

}

for(int k=0;k<4;k++)

{

int x=i+xx[k],y=j+yy[k];

if(x>=1&&x<=m&&y>=1&&y<=p)

{

int pos2=(x-1)*p+y;

addedge(pos+num,pos2,inf);

}

}

if(i==1||i==m||j==1||j==p)//边界

{

addedge(pos+num,t,inf);

}

}

}

int ans=sap();

printf("%d\n",ans);

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: