平面图->对偶图

平面图

若对于一个在平面上的图 \(G\) ,有 \(\forall u,v\in G\),其交点为 \(G\) 顶点,则称这个图为平面图。

对偶图

在原图的边隔开的每个面上选一个点,若两个点相连穿过且仅穿过一条边就将它俩连起来,这条边的边权即为原图被穿过的边的边权

\(↑\)懒得画图也不太会用人类语言描述,感性理解(

因为可以将对偶图的边权看作删除原图的边的代价,所以对偶图上的最短路就是原图最小割

对偶图建图是怎么回事呢?对偶图相信大家都很熟悉,但是对偶图建图是怎么回事呢,下面就让我们一起了解吧。
对偶图建图,其实就是将平面图转换为对偶图,大家可能会很惊讶对偶图怎么会建图呢?但事实就是这样,我也感到非常惊讶。
这就是关于对偶图建图的事情了,大家有什么想法呢。

//4001
#include <bits/stdc++.h>
using namespace std;

long long read()
{
	long long res=0,p=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-')p=-1; ch=getchar();}
	while(isdigit(ch)) res=res*10+ch-'0',ch=getchar();
	return res*p;
}

const int maxn=2010,inf=0x3f3f3f3f;

int n,m,sumn;
long long ans;
int line[maxn][maxn],cur[maxn][maxn],row[maxn][maxn];
long long dis[maxn*maxn*2];
bool vis[maxn*maxn*2];
int s,t;
int head[maxn*maxn*2],cnt;

struct note
{
	int nxt,to,val;
}ed[maxn*maxn*4];

void add(int u,int v,int w)
{
	ed[++cnt].nxt=head[u],ed[cnt].to=v,ed[cnt].val=w,head[u]=cnt;
}

int id(int x,int y,int flag)
{
	if(((x-1)*m+y)*2+flag==t) cout<<x<<" "<<y<<endl;
	return ((x-1)*m+y)*2+flag;
}

struct node
{
	int pos,dis;
	bool operator < (const node &x) const
	{
		return x.dis<dis;
	}
};

priority_queue<node> q;

void dij()
{
	q.push((node){s,0}),memset(dis,0x3f,sizeof(dis)),dis[s]=0;
	while(!q.empty())
	{
		node now=q.top();q.pop();
		int u=now.pos;
		if(vis[u]) continue ;
		vis[u]=1;
		for(int i=head[u];i;i=ed[i].nxt)
		{
			int v=ed[i].to,w=ed[i].val;
			if(dis[v]>dis[u]+w)
			{
				dis[v]=dis[u]+w;
				if(!vis[v]) q.push((node){v,dis[v]});
			}
		}
	}
}

int main()
{
	n=read(),m=read(),sumn=(n-1)*(m-1)*2,s=0,t=n*m*2+1;
	if(n==1||m==1)
	{
		n=max(n,m),ans=inf;
		for(int i=1;i<=n;++i) ans=min(ans,read());
		cout<<ans;
		return 0;
	}
	for(int i=1;i<=n;++i) for(int j=1;j<m;++j) line[i][j]=read();
	for(int i=1;i<n;++i) for(int j=1;j<=m;++j) row[i][j]=read();
	for(int i=1;i<n;++i) for(int j=1;j<m;++j) cur[i][j]=read();
	for(int i=1;i<m;++i) add(id(1,i,0),t,line[1][i]),add(s,id(n-1,i,1),line[n][i]),add(id(n-1,i,1),s,line[n][i]),add(t,id(1,i,0),line[1][i]);
	for(int i=1;i<n;++i) add(s,id(i,1,1),row[i][1]),add(id(i,m-1,0),t,row[i][m]),add(id(i,1,1),s,row[i][1]),add(t,id(i,m-1,0),row[i][m]);
	for(int i=1;i<n;++i)
	{
		for(int j=1;j<m;++j)
		{
			if(i>1) add(id(i,j,0),id(i-1,j,1),line[i][j]);
			if(j<m-1) add(id(i,j,0),id(i,j+1,1),row[i][j+1]);
			if(j>1) add(id(i,j,1),id(i,j-1,0),row[i][j]);
			if(i<n-1) add(id(i,j,1),id(i+1,j,0),line[i+1][j]);
			add(id(i,j,1),id(i,j,0),cur[i][j]),add(id(i,j,0),id(i,j,1),cur[i][j]);
		}
	}
	dij();
	cout<<dis[t];
	return 0;
}

上一篇:[洛谷P4389] 付公主的背包


下一篇:烦人的幻灯片 Sorting Slides