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的点都代表了一种割法。所以最短路和最小割等价。
另外,本题图长什么样给你了,比较方便。有些题只告诉你是平面图,面和点要自己找,如果遇到,请至网上自行找板子。
附程序:
参考资料:
最大最小定理(平面图最小割
对偶图)周冬
对偶图的应用【思考】
这题就是一道裸的最小割[什么你看不出来],求最小割去多少边,使得起点与终点不连通。
于是你就试着写流(滑稽。
===========================乌龟天空游,火星撞地球
什么你写流过了(滑稽。
让我们来算一算,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; }
相关文章推荐
- matlab调用c++,应该用mex把cpp编译成 .mex文件供MATLAB在命令行方式下调用吧
- mysql时间函数练习
- oracle的最大连接数
- nginx限流算法
- 原生js的各种方法
- UNITY3D 贴图格式压缩说明
- HTML5基础知识(2)--标题标签的使用
- 接口
- mysql流程函数练习
- 基类构造和派生构造
- 面向vs10使用的GDAL库编译Win7(32/64)(图文教程+亲测可用!)
- oracle中如何设置主键并且让其自动增长
- java重载与覆盖
- Binder连接池的实现步骤
- Jeecg心得
- ssh
- Codeforces Round #359 (Div. 2) D. Kay and Snowflake
- css总结
- Meanshift filter实现简单图片的卡通化效果
- 【操作系统】实验四 主存空间的分配和回收