您的位置:首页 > 其它

bzoj 1001 BJOI2006 狼抓兔子 最小割

2015-01-03 23:57 232 查看

bzoj 1001 BJOI2006 狼抓兔子

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1001

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

Sample Output

14

本题即求最小割,难点在于建模(建对偶图):
对于每一个面,建一个点,对于每一条边,在对偶图中也连边;
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<queue>
#define INF 0x3f3f3f3f
#define MAXN 3000000+10

using namespace std;

bool used[MAXN];
int n,m,e,t;
int to[MAXN],next[MAXN],edge[MAXN],val[MAXN],dis[MAXN];

struct Node
{
int v,dis;
Node(int x,int y)
{
v=y;
dis=x;
}
bool operator <(Node x)const
{
return dis>x.dis;
}
};
void addedge(int x,int y,int v)
{
e++;
to[e]=y;
val[e]=v;
next[e]=edge[x];
edge[x]=e;
}

void Dijstra()
{
memset(dis,INF,sizeof(dis));
priority_queue<Node> q;
dis[0]=0;
q.push(Node(dis[0],0));
while(!q.empty())
{
Node tmp=q.top();
q.pop();
if(!used[tmp.v])
{
int k=tmp.v;
used[k]=true;
for(int i=edge[k]; i; i=next[i])
if(!used[to[i]])
{
if(dis[to[i]]>dis[k]+val[i])
{
dis[to[i]]=dis[k]+val[i];
q.push(Node(dis[to[i]],to[i]));
}
}
}
}
printf("%d",dis[t]);

}

bool check()
{
if(n==1)
{
int ans=INF;
for(int i=1,res; i<=m; i++)
{
scanf("%d",&res);
ans=min(res,ans);
}
printf("%d",ans);
return false;
}
if(m==1)
{
int ans=INF;
for(int i=1,res; i<=n; i++)
{
scanf("%d",&res);
ans=min(res,ans);
}
printf("%d",ans);
return false;
}
return true;
}
void make_map()
{
int res;
t=2*(n-1)*(m-1)+1;
for(int i=1; i<m; i++)
{
scanf("%d",&res);
addedge(i*2,t,res);
}
for(int i=1; i<n-1; i++)
{
for(int j=1; j<m; j++)
{
scanf("%d",&res);
addedge(i*(m-1)*2+j*2,(i-1)*(m-1)*2-1+j*2,res);
}
}
for(int i=1; i<m; i++)
{
scanf("%d",&res);
addedge(0,(n-2)*(m-1)*2-1+i*2,res);
}
for(int i = 0; i < n - 1; i++)
{
scanf("%d",&res);
addedge(0,i * (m - 1) * 2 + 1,res);
for(int j = 1; j < m - 1; j++)
{
scanf("%d",&res);
addedge(i * (m - 1) * 2 + j * 2,i * (m - 1) * 2 + j * 2 + 1,res);
}
scanf("%d",&res);
addedge((i + 1) * (m - 1) * 2,t,res);
}
//step3:
for(int i = 0; i < n - 1; i++)
{
for(int j = 1; j < m; j++)
{
scanf("%d",&res);
addedge(i * (m - 1) * 2 + j * 2 - 1,i * (m - 1) * 2 + j * 2,res);
}
}

}

void work()
{
make_map();
Dijstra();
}

void readdata()
{
scanf("%d%d",&n,&m);
if(check())
work();
}

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