[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 }