把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P2046 [NOI2010] 海拔

题面传送门
居然还有这种做法,学到了学到了。
首先这个肯定是有一条分割线,上半边为\(0\),下半边为\(1\),证明显然。
所以这启发我们跑最小割。
但是这个东西T了一个点。
考虑到这个是一张平面图,可以转化成对偶图然后跑最短路即可。时间复杂度\(O(SPFA)\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 300000
#define M 200000
#define W (1<<20)
#define mod 998244353
#define eps (1e-5)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
using namespace std;
int n,m,z,now,S,T,d[N+5],Ans;
struct yyy{int to,w,z;}tmp;queue<int> Q;
struct ljb{int head,h[N+5];yyy f[N+5<<3];I void add(int x,int y,int z){f[++head]=(yyy){y,z,h[x]};h[x]=head;/*printf("%d %d %d\n",x,y,z);*/}}s;
int main(){
	freopen("1.in","r",stdin);freopen("1.out","w",stdout);
	re int i,j;Me(d,0x3f);scanf("%d",&n);d[S=0]=0;T=n*n+1;
	for(i=1;i<=n+1;i++){
		for(j=1;j<=n;j++){
			scanf("%d",&z);if(i==1) s.add(S,d(i,j),z);else if(i==n+1)s.add(d(i-1,j),T,z);else s.add(d(i-1,j),d(i,j),z);
		}
	}
	for(i=1;i<=n;i++) {
		for(j=1;j<=n+1;j++) {
			scanf("%d",&z);if(j==1)s.add(d(i,j),T,z);else if(j==n+1) s.add(S,d(i,j-1),z);else s.add(d(i,j),d(i,j-1),z);
		}
	}
	for(i=1;i<=n+1;i++){
		for(j=1;j<=n;j++){
			scanf("%d",&z);if(i==n+1) s.add(T,d(i-1,j),z);else if(i==1)s.add(d(i,j),S,z);else s.add(d(i,j),d(i-1,j),z);
		}
	}
	for(i=1;i<=n;i++) {
		for(j=1;j<=n+1;j++) {
			scanf("%d",&z);if(j==n+1)s.add(d(i,j-1),S,z);else if(j==1) s.add(T,d(i,j),z);else s.add(d(i,j-1),d(i,j),z);
		}
	}
	Q.push(S);while(!Q.empty()){
		now=Q.front();Q.pop();for(i=s.h[now];i;i=tmp.z){
			tmp=s.f[i];if(d[tmp.to]<=d[now]+tmp.w) continue;d[tmp.to]=d[now]+tmp.w;Q.push(tmp.to);
		}
	}printf("%d\n",d[T]);
}
posted @ 2021-07-25 18:31  275307894a  阅读(44)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end