【bzoj2007】 Noi2010—海拔

http://www.lydsy.com/JudgeOnline/problem.php?id=2007 (題目連接)php

題意

  $(n+1)*(n+1)$的網格圖上,相鄰兩點間有一些人流。左上角點的海拔$0$,右下角海拔$1$,沒單位人流從海拔低的地方走到海拔高的地方會消耗對應的體力。問最少消耗多少體力。ios

Solution

  最小割很顯然,轉爲對偶圖跑Dijkstra就行了。spa

  用pair寫個堆各類奇怪的錯誤是smg,建圖還建錯了,今天晚上不適合寫題= =blog

細節

  priority_queue默認大根堆= =。get

代碼

// bzoj2007
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf (1ll<<30)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std;

const int maxn=1000010;
int head[maxn],dis[maxn],vis[maxn],n,S,T,cnt;
struct edge {int to,next,w;}e[maxn<<2];

void link(int u,int v,int w) {
	e[++cnt]=(edge){v,head[u],w};head[u]=cnt;
}
int Dijkstra() {
	for (int i=S;i<=T;i++) dis[i]=inf;dis[S]=0;
	priority_queue<pair<int,int> >q;q.push(pair<int,int>(0,S));
	while (!vis[T]) {
		pair<int,int> x=q.top();q.pop();
		if (vis[x.second]) continue;
		vis[x.second]=1;
		for (int i=head[x.second];i;i=e[i].next)
			if (!vis[e[i].to] && dis[e[i].to]>e[i].w-x.first) {
				dis[e[i].to]=e[i].w-x.first;
				q.push(pair<int,int>(-dis[e[i].to],e[i].to));
			}
	}
	return dis[T];
}
int main() {
	scanf("%d",&n);
	S=0,T=n*n+1;
	for (int i=0;i<=n;i++)
		for (int x,j=1;j<=n;j++)
			scanf("%d",&x),link(max(S,(i-1)*n+j),min(T,i*n+j),x);
	for (int i=0;i<n;i++)
		for (int x,j=1;j<=n+1;j++)
			scanf("%d",&x),link(j==n+1 ? S : i*n+j,j==1 ? T : i*n+j-1,x);
	for (int i=0;i<=n;i++)
		for (int x,j=1;j<=n;j++)
			scanf("%d",&x),link(min(T,i*n+j),max(S,(i-1)*n+j),x);
	for (int i=0;i<n;i++)
		for (int x,j=1;j<=n+1;j++)
			scanf("%d",&x),link(j==1 ? T : i*n+j-1,j==n+1 ? S :i*n+j,x);
	printf("%d",Dijkstra());
	return 0;
}
相關文章
相關標籤/搜索