您的位置:首页 > 其它

BZOJ 1001 狼抓兔子 [最小割转最短路=平面图转对偶图]

2016-06-24 19:24 375 查看
原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001

参考资料:


最大最小定理(平面图最小割
对偶图)周冬

对偶图的应用

【思考】
这题就是一道裸的最小割[什么你看不出来],求最小割去多少边,使得起点与终点不连通。
于是你就试着写流(滑稽。

===========================乌龟天空游,火星撞地球

什么你写流过了(滑稽。
让我们来算一算,n,m<=1000,最多有999*1000+1000*999+999*999=2996001条边,1000*1000=1000000个点,这样跑一个流。
/*
老师告诉我们:写作文要引用名人名言!
lbn187大神曾经说过:网络流跑200000万条边完全没问题!!!
所以写流是可以过的(滑稽
*/
不TLE才怪。

这是一条普通的分割线===========================

这时候我们需要一个更加快速的方法来算最小割。
这里用到了把最小割转换成最短路,把平面图转换成对偶图的方法。主要思想如下:
①把每一个图中的面积块当作新的点。
②每一条边都与两个面相连,把面看作点后,这条边连接这两个面化作的点,权值不变。
③连接起点与终点,把外面的最大平面分成两份,分别为最短路的起点与终点。
④跑一边最短路即可。

附图:



可以看出每一条从0到13的点都代表了一种割法。所以最短路和最小割等价。
另外,本题图长什么样给你了,比较方便。有些题只告诉你是平面图,面和点要自己找,如果遇到,请至网上自行找板子。

附程序:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <windows.h>
#define rep(j,k,l) for (int j=k;j<=l;j++)

using namespace std;
int n,m,nn,mm,v[7000000][2],ne[7000000],st[2500000],lych[2500000],num[2500000];
bool used[2500000];

void add(int k,int l,int o){

v[++mm][1]=l;
v[mm][0]=o;
ne[mm]=st[k];
st[k]=mm;
v[++mm][1]=k;
v[mm][0]=o;
ne[mm]=st[l];
st[l]=mm;

}

int main(){

scanf("%d%d",&n,&m);
nn=(n-1)*(m-1)*2+1;mm=0;
rep(i,1,n)
rep(j,1,m-1){

int k;
scanf("%d",&k);
if (i==1) add(j*2,nn,k);
else if (i==n) add((n-2)*(m-1)*2+j*2-1,0,k);
else add((i-2)*(m-1)*2+j*2-1,(i-1)*(m-1)*2+j*2,k);

}

rep(i,1,n-1)
rep(j,1,m){

int k;
scanf("%d",&k);
if (j==1) add(0,(i-1)*(m-1)*2+1,k);
else if (j==m) add(nn,i*(m-1)*2,k);
else add((i-1)*(m-1)*2+(j-1)*2,(i-1)*(m-1)*2+(j-1)*2+1,k);

}

rep(i,1,n-1)
rep(j,1,m-1){

int k;
scanf("%d",&k);
add((i-1)*(m-1)*2+j*2-1,(i-1)*(m-1)*2+j*2,k);

}

/*rep(i,0,nn){

printf("%d\n",i);
for (int j=st[i];j!=0;j=ne[j])
printf("%d %d\n",v[j][1],v[j][0]);

}*/

int head=0,tail=1;lych[1]=0;used[0]=1;num[0]=1;
while (head!=tail){

head=(head+1)%2000000;int k=lych[head];used[k]=0;
for (int i=st[k];i!=0;i=ne[i]){

int l=v[i][1];
if (num[l]==0||num[l]>num[k]+v[i][0]){

num[l]=num[k]+v[i][0];
if (used[l]==0){

tail=(tail+1)%2000000;
lych[tail]=l;

}

}

}

}
printf("%d\n",num[nn]-1);
system("pause");
return 0;

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