首页 > 代码库 > 【BZOJ2007】【Noi2010】海拔 平面图最小割转最短路

【BZOJ2007】【Noi2010】海拔 平面图最小割转最短路

#include <stdio.h>
int main()
{
	puts("转载请注明出处谢谢");
	puts("http://blog.csdn.net/vmurder/article/details/43280891");
}


题解:这个模型很水,不需要极角序神马转对偶图,直接乱搞就行。

然后目的是把图割开,那么只需要跑S->T最短路就行。


要做平面图转对偶图不妨去这篇。

【BZOJ2965】保护古迹 平面图转对偶图,暴力,网络流

还有就是某人说堆很快233,我弱弱的优先队列竟然,嘿嘿。

@jiangyuze831

BZOJ 2007 NOI 2010 海拔 平面图最小割->最短路SPFA+pq

代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 505
#define P 250100
#define M 1501000
using namespace std;
struct KSD
{
	int v,len,next;
}e[M];
int head[P],cnt;
inline void add(int u,int v,int len)
{
	e[++cnt].v=v;
	e[cnt].len=len;
	e[cnt].next=head[u];
	head[u]=cnt;
}
struct YYC
{
	int f,v;
	bool operator < (const YYC &a)const{return f>a.f;}
	YYC(int _f=0,int _v=0):f(_f),v(_v){}
};
int dist[P],s,t;
priority_queue<YYC>pq;
int spfa()
{
	while(!pq.empty())pq.pop();
	memset(dist,0x3f,sizeof dist);

	int i,u,v;
	pq.push(YYC(dist[s]=0,s));
	while(!pq.empty())
	{
		YYC U=pq.top();pq.pop();
		if(dist[u=U.v]!=U.f)continue;
		for(i=head[u];i;i=e[i].next)
		{
			v=e[i].v;
			if(dist[v]>dist[u]+e[i].len)
			{
				dist[v]=dist[u]+e[i].len;
				pq.push(YYC(dist[v],v));
			}
		}
	}
	return dist[t];
}
int n,id[N][N];
void build()
{
	int i,j,k;
	scanf("%d",&n),s=n*n+1,t=n*n+2;
	for(i=1;i<=n;i++)for(j=1;j<=n;j++)id[i][j]=++cnt;
	for(i=1;i<=n;i++)id[0][i]=id[i][n+1]=s,id[i][0]=id[n+1][i]=t;
		cnt=0;
	for(i=1;i<=n+1;i++)for(j=1;j<=n;j++)
	{
		scanf("%d",&k);
		add(id[i-1][j],id[i][j],k);
	}
	for(i=1;i<=n;i++)for(j=1;j<=n+1;j++)
	{
		scanf("%d",&k);
		add(id[i][j],id[i][j-1],k);
	}
	for(i=1;i<=n+1;i++)for(j=1;j<=n;j++)
	{
		scanf("%d",&k);
		add(id[i][j],id[i-1][j],k);
	}
	for(i=1;i<=n;i++)for(j=1;j<=n+1;j++)
	{
		scanf("%d",&k);
		add(id[i][j-1],id[i][j],k);
	}
}
int main()
{
	freopen("test.in","r",stdin);
	build();
	printf("%d\n",spfa());
	return 0;
}


【BZOJ2007】【Noi2010】海拔 平面图最小割转最短路