#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; }
时间: 2024-10-27 09:42:49