[BZOJ2007][NOI2010]海拔(对偶图最短路)

首先确定所有点的海拔非0即1,问题转化成裸的平面图最小割问题,进而转化成对偶图最短路(同BZOJ1002)。

这题的边是有向的,所以所有边顺时针旋转90度即可。

如下图(S和T的位置是反的)。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 #include<algorithm>
 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 6 using namespace std;
 7  
 8 priority_queue<pair<int,int> > q;
 9  
10 const int N=1003000;
11 int x,S,T,h[N],to[N],val[N],nxt[N],cnt,dis[N],vis[N],n,num[510][510];
12  
13 void add(int x,int y,int z){ to[++cnt]=y; val[cnt]=z; nxt[cnt]=h[x]; h[x]=cnt; }
14 
15 void work(){
16     memset(dis,0x3f,sizeof(dis)); dis[S]=0;
17     q.push(make_pair(0,S));
18     while(!q.empty()){
19         x=q.top().second; q.pop();
20         if(vis[x]) continue;
21         vis[x]=1;
22         for(int i=h[x]; i; i=nxt[i])
23             if (dis[to[i]]>dis[x]+val[i])
24                 dis[to[i]]=dis[x]+val[i],q.push(make_pair(-dis[to[i]],to[i]));
25     }
26 }
27 
28 int main(){
29     freopen("bzoj2007.in","r",stdin);
30     freopen("bzoj2007.out","w",stdout);
31     scanf("%d",&n); S=0; T=n*n+1;
32     rep(i,1,n) num[0][i]=num[i][n+1]=S,num[i][0]=num[n+1][i]=T;
33     rep(i,1,n) rep(j,1,n) num[i][j]=n*(i-1)+j;
34     rep(i,0,n) rep(j,1,n) scanf("%d",&x),add(num[i][j],num[i+1][j],x);
35     rep(i,1,n) rep(j,0,n) scanf("%d",&x),add(num[i][j+1],num[i][j],x);
36     rep(i,0,n) rep(j,1,n) scanf("%d",&x),add(num[i+1][j],num[i][j],x);
37     rep(i,1,n) rep(j,0,n) scanf("%d",&x),add(num[i][j],num[i][j+1],x);
38     work(); printf("%d\n",dis[T]);
39     return 0;
40 }

 

posted @ 2018-08-02 17:46  HocRiser  阅读(273)  评论(0编辑  收藏  举报