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;
}
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;
}
相关文章推荐
- JOJ 2724 hua rong dao (最小割 拆点)[无代码]
- zoj 2724 Windows Message Queue(最小优先队列+STL)
- CJOJ 2427 最小生成树
- CJOJ 2484 函数最小值 / Luogu 2085 函数最小值
- JOJ 2656: 霍格瓦兹魔法阵 //最小割
- JOJ 1170 :Wire Is So Expensive 最小生成树
- poj 2724 Purifying Machine (最小边覆盖)
- joj 2672 Hanoi Tower Once More 有向无环图的最小路径覆盖=N-最大匹配
- HDU2724 Tree【最小生成树】
- joj 2656: 霍格瓦兹魔法阵 最小割
- poj 2724 Purifying Machine 最小路径覆盖
- joj 1167 How Many Eggs Do I Have?
- #分支限界法#最小机器重量设计问题(优先队列)
- 网络费用流-最小k路径覆盖
- 二维数组最小路径和(算法)
- 最小生成树变形 —— nyoj 1239 引水工程
- 线性回归——最小二乘法_实例(二)
- 旋转数组的最小数字
- 【python算法】为了找到最小的可分配ID实例
- hdu 1162 Eddy's picture(最小生成树Prim算法)