#include <stdio.h>
int main()
{
puts("转载请注明出处谢谢");
puts("http://blog.csdn.net/vmurder/article/details/43280891");
}
题解:这个模型很水,不需要极角序神马转对偶图,直接乱搞就行。
然后目的是把图割开,那么只需要跑S->T最短路就行。
要做平面图转对偶图不妨去这篇。
还有就是某人说堆很快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;
}