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
HINT
2015.4.16新加数据一组,可能会卡掉从前可以过的程序。
Source
一眼看出是最小割
但是直接写最大流就萎了…因为有10^6个点(当然是因为我的最大流比较丑跑得慢)
所以学平面图的时候顺便学了平面图和对偶图的关系
这个题给的图一看就是个很明显的平面图
对它建出对偶图之后应用最短路和最小割之间的对应关系以网络流的源点为起点跑一遍Heap-Dijkstra
最后到汇点的最短路距离就是原图的最小割答案.
跟着黄学长学了平面图转对偶图的姿势.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define MAXN 2000100
using namespace std;
int n,m,size,top;
struct edge
{
int to,w;
edge *next;
}e[MAXN<<2],*prev[MAXN];
void in(int &x)
{
x=0;char ch=getchar();int flag=1;
while (!(ch>='0'&&ch<='9')) flag=ch=='-'?-1:flag,ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();x*=flag;
}
struct node
{
int x,dis;
bool operator <(const node& a)const
{
return dis>a.dis;
}
};
priority_queue<node> q;
int dis[MAXN];
bool vis[MAXN];
void insert(int u,int v,int w)
{
e[++top].to=v;e[top].next=prev[u];e[top].w=w;prev[u]=&e[top];
}
void dijkstra(int s)
{
memset(dis,0x3f,sizeof(dis));
q.push((node){s,0});dis[s]=0;
while (!q.empty())
{
node t=q.top();q.pop();
if (vis[t.x]) continue;
for (edge *i=prev[t.x];i;i=i->next)
if (dis[i->to]>t.dis+i->w)
{
dis[i->to]=t.dis+i->w;
q.push((node){i->to,dis[i->to]});
}
vis[t.x]=1;
}
}
int main()
{
in(n);in(m);size=(n*m-n-m+1)<<1;int w;
for (int i=1;i<m;i++) in(w),insert(i,size+1,w),insert(size+1,i,w);
for (int i=1;i<n-1;i++)
for (int j=1;j<m;j++)
{
in(w);
int u=(i<<1)*(m-1)+j,v=((i<<1)-1)*(m-1)+j;
insert(u,v,w);insert(v,u,w);
}
for (int i=1;i<m;i++)
{
in(w);
int u=0,v=((n<<1)-3)*(m-1)+i;
insert(u,v,w);insert(v,u,w);
}
for (int i=0;i<n-1;i++)
for (int j=1;j<=m;j++)
{
in(w);
int u,v;
if (j==1) u=0,v=(i<<1)*(m-1)+m;
else
if (j==m) u=(i<<1|1)*(m-1),v=size+1;
else u=(i<<1)*(m-1)+j-1,v=(i<<1)*(m-1)+j+m-1;
insert(u,v,w);insert(v,u,w);
}
for (int i=0;i<n-1;i++)
for (int j=1;j<m;j++)
{
in(w);
int u=(i<<1|1)*(m-1)+j,v=(i<<1)*(m-1)+j;
insert(u,v,w);insert(v,u,w);
}
dijkstra(0);
printf("%d",dis[size+1]);
}