思路:

1.按照题意求最小割 转换成最大流用Dinic解

2. 转换成对偶图 求最短路

Dinic:

//By SiriusRen
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1100000
int n,m,first[N],next[N*6],v[N*6],w[N*6],tot,jy,ans,vis[N],S,T,xx,pos[N];
void Add(int x,int y,int z){w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;}
void add(int x,int y,int z){Add(x,y,z),Add(y,x,z);}
bool tell(){
memset(vis,-1,sizeof(vis)),vis[S]=0;
queue<int>q;q.push(S);
while(!q.empty()){
int t=q.front();q.pop();
for(int i=first[t];~i;i=next[i])
if(w[i]&&vis[v[i]]==-1)
vis[v[i]]=vis[t]+1,q.push(v[i]);
}return vis[T]!=-1;
}
int zeng(int x,int y){
if(x==T)return y;
int r=0;
for(int i=first[x];~i&&y>r;i=next[i])
if(w[i]&&vis[v[i]]==vis[x]+1){
int t=zeng(v[i],min(y-r,w[i]));
w[i]-=t,w[i^1]+=t,r+=t;
}
if(!r)vis[x]=-1;
return r;
}
int main(){
memset(first,-1,sizeof(first));
scanf("%d%d",&n,&m);
S=m+1,T=n*m+m;
for(int i=1;i<=n;i++)for(int j=1;j<m;j++)
scanf("%d",&xx),add(i*m+j,i*m+j+1,xx);
for(int i=1;i<n;i++)for(int j=1;j<=m;j++)
scanf("%d",&xx),add(i*m+j,(i+1)*m+j,xx);
for(int i=1;i<n;i++)for(int j=1;j<m;j++)
scanf("%d",&xx),add(i*m+j,(i+1)*m+j+1,xx);
while(tell())while(jy=zeng(S,0x3fffffff))ans+=jy;
printf("%d\n",ans);
}

Dijkstra:



这么转成对偶图

在原平面图中添加一条从起点S到终点T的边,会增加一个区域S’。

无限大的区域设为T’。

把加边后的平面图按照上面的方法转化为对偶图。

删去边S’-T’。

此时S-T的最小割大小等于S’到T’的最短路长度。

Ps:需要特判n=1|m=1的情况

//By SiriusRen
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
#define M 1111*1111*6
int n,m,a[1005][1005],b[1005][1005],c[1005][1005],T=2000*1005;
int first[M/3],next[M],v[M],w[M],tot,vis[M/3],d[M/3];
void Add(int x,int y,int z){w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;}
struct Node{int now,weight;}jy;
bool operator < (Node a,Node b){return a.weight>b.weight;}
void Dijkstra(){
priority_queue<Node>pq;pq.push(jy);
while(!pq.empty()){
Node t=pq.top();pq.pop();
if(vis[t.now])continue;
for(int i=first[t.now];~i;i=next[i])if(d[v[i]]>d[t.now]+w[i])
d[v[i]]=d[t.now]+w[i],jy.now=v[i],jy.weight=d[v[i]],pq.push(jy);
}printf("%d\n",d[T]=0x3f3f3f3f?d[T]:0);
}
void add(int x,int y,int z){Add(x,y,z),Add(y,x,z);}
int main(){
memset(first,-1,sizeof(first)),memset(d,0x3f,sizeof(d)),d[0]=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)for(int j=1;j<m;j++)scanf("%d",&a[i][j]);
for(int i=1;i<n;i++)for(int j=1;j<=m;j++)scanf("%d",&b[i][j]);
for(int i=1;i<n;i++)for(int j=1;j<m;j++)scanf("%d",&c[i][j]);
if(n==1||m==1){
if(m==1)for(int i=1;i<n;i++)d[T]=min(d[T],b[i][1]);
if(n==1)for(int i=1;i<m;i++)d[T]=min(d[T],a[1][i]);
}
for(int i=1;i<n;i++)for(int j=1;j<m;j++){
int cnt=((i-1)*(m-1)+j)*2;
add(cnt-1,cnt,c[i][j]);
if(j!=m-1)add(cnt-1,cnt+2,b[i][j+1]);
if(i!=n-1)add(cnt,cnt+(m-1)*2-1,a[i+1][j]);
}
for(int i=1;i<n;i++)add(((i-1)*(m-1)+1)*2,T,b[i][1]),add(0,2*i*(m-1)-1,b[i][m]);
for(int i=1;i<m;i++)add(0,2*i-1,a[1][i]),add(2*((n-2)*(m-1)+i),T,a[n][i]);
Dijkstra();
}



效率竟然差不多?

BZOJ 1001 平面图与对偶图的转化 最短路Or最大流的更多相关文章

  1. bzoj 1001 平面图转对偶图 最短路求图最小割

    原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=1001 整理了下之前A的题 平面图可以转化成对偶图,然后(NlogN)的可以求出图的最小割( ...

  2. BZOJ 1001 平面图转对偶图

    原图的面转成点,原图的边依旧边,只是连接的是两个面. 对偶图的点数=原图的面数 对偶图的边数=原图的边数(如果原边只属于一个面,则它为环边) #include<bits/stdc++.h> ...

  3. bzoj 1001 狼抓兔子 —— 平面图最小割(最短路)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1001 平面图最小割可以转化成最短路问题: 建图时看清楚题目的 input ... 代码如下: ...

  4. [jzoj 6092] [GDOI2019模拟2019.3.30] 附耳而至 解题报告 (平面图转对偶图+最小割)

    题目链接: https://jzoj.net/senior/#main/show/6092 题目: 知识点--平面图转对偶图 在求最小割的时候,我们可以把平面图转为对偶图,用最短路来求最小割,这样会比 ...

  5. BZOJ 1001 狼抓兔子 (网络流最小割/平面图的对偶图的最短路)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 算法讨论: 1.可以用最大流做,最大流等于最小割. 2.可以把这个图转化其对偶图,然 ...

  6. BZOJ 1001 [BeiJing2006] 狼抓兔子(平面图最大流)

    题目大意 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的.而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: ...

  7. s - t 平面图最大流 (附例题 bzoj 1001)

    以下均移自 周冬的<两极相通-浅析最大最小定理在信息学竞赛中的应用> 平面图性质 1.(欧拉公式)如果一个连通的平面图有n个点,m条边和f个面,那么f=m-n+2 2.每个平面图G都有一个 ...

  8. 【BZOJ 1001】狼抓兔子 对偶图+SPFA

    这道题是求图的最小割,也就是用最大流.但因为边太多,最大流算法会T,因此不能用最大流算法. 因为这是个平面图,所以求平面图的最小割可以使用特殊的技巧就是求对偶图然后求对偶图的最短路.把每个面看成一个点 ...

  9. 【BZOJ 2007】 2007: [Noi2010]海拔 (平面图转对偶图+spfa)

    2007: [Noi2010]海拔 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2504  Solved: 1195 Description YT市 ...

随机推荐

  1. Java ThreadLocal类学习

    ThreadLocal为线程局部变量,通过线程名(key)-对象(value)的Map来获取每个线程对应的对象.我们不能通过ThreadLocal处理多线程并发问题,但是每个线程可以通过ThreadL ...

  2. Android 的Recovery机制

    Android 的Recovery机制 文件夹 1. 系统的启动模式 1 1.1 Android系统的启动模式 1 1.2 系统的启动模式 2 2. Recovery模式中的三个部分 3 3. Rec ...

  3. Java 定制工具库 —— Print(import static)

    创建自己的工具库以减少或消除重复的程序代码.例如,我们在Print类中,对常常用到的System.out.println()封装调用以减少输入负担.这样,我们在使用该类时,可以用一个更具可读性的 im ...

  4. Oracle11g数据库导入Oracle10g数据库操作笔记

    一.在11g服务器上,使用expdp命令备份数据 EXPDP USERID='SYS/sys@daggis as sysdba' schemas=oa directory=DATA_PUMP_DIR ...

  5. Objective-C —内存管理(上)

    内存管理 一.为什么要进行内存管理 移动设备的内存极其有限,每个app所能占用的内存是有限制的 下列行为都会增加一个app的内存占用 创建一个OC对象 定义一个变量 调用一个函数或者方法 内存占用多大 ...

  6. POJ 3269 中位数

    题意: 思路: 这道题坑也不少.. 你准备好脑洞了么? 首先 要认真审题 题目中有说:"没有两头牛的吃草位置是相邻的" 这句话让我们省了很多的事儿 (Discuss里有的大神就入了 ...

  7. 线上服务CPU100%问题快速定位实战--转

    来自微信公众号 架构师之路 功能问题,通过日志,单步调试相对比较好定位. 性能问题,例如线上服务器CPU100%,如何找到相关服务,如何定位问题代码,更考验技术人的功底. 58到家架构部,运维部,58 ...

  8. C#线程调用带参数的方法,给控件赋值

    System.Threading.Thread thread = new System.Threading.Thread(() => { //各种业务 //定义一个委托 public deleg ...

  9. C++之const关键字

    本文引自http://www.cnblogs.com/lichkingct/archive/2009/04/21/1440848.html ,略有增删 const关键字在c++中用法有很多,总结如下: ...

  10. 使用js获取url中的get参数并转成json格式

    写在前面的 没啥说的 上代码 思路就是先获取到?后面的参数区,然后 利用字符串转数组方法获取到各个参数 var json = {}; var url = 'https://www.baidu.com/ ...