思路:

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. [HTML5] Inlining images with SVG and data URIs

    The main reason you want to do I"nlining images with SVG and data URIs" is to reduce http ...

  2. hdu 3449 Consumer (依赖01背包)

    题目: 链接:pid=3449">点击打开链接 题意: 思路: dp[i][j]表示前i个箱子装j钱的材料可以得到的最大价值. 代码: #include<iostream> ...

  3. 零基础学python-5.2 数字表达式操作符

    表达式是处理数字最主要的工具 a=1#常量 a=a+1#表达式 操作符 操作符 描写叙述 yield 生成 器函数发送协议 lambda args:expression 生成匿名函数 x if y e ...

  4. java mail邮件发送(带附件) 支持SSL

    java mail邮件发送(带附件)有三个类 MailSenderInfo.java package mail; import java.util.Properties; import java.ut ...

  5. 开源TT框架上的日志类

    public class Logger { /** * log tag */ private String tagName = "MoGuLogger";// tag name / ...

  6. 通过setInterval函数在地图上每隔1s打一次点

    <?php echo <<<_END <!doctype html> <html> <head> <meta charset=&quo ...

  7. 在openwrt上编译一个最简单的ipk包

    1 什么是opkg Opkg 是一个轻量快速的套件管理系统,目前已成为 Opensource 界嵌入式系统标准.常用于路由.交换机等嵌入式设备中,用来管理软件包的安装升级与下载. opkg updat ...

  8. Stop being a perfectionist

    节选自 7 Things You Need To Stop Doing To Be More Productive, Backed By Science “We found that perfecti ...

  9. 新疆大学OJ(ACM) 1099: 数列有序!

    1099: 数列有序! 时间限制: 1 Sec  内存限制: 128 MB 题目描述 有n(n<=100)个整数,已经按照从小到大顺序排列好,现在另外给一个整数x,请将该数插入到序列中,并使新的 ...

  10. php计算两个日期相差的天数

    /** * 时间差计算 * * @param Timestamp $time * @return String Time Elapsed */ function time2Units ($time,$ ...