http://www.lydsy.com/JudgeOnline/problem.php?id=2007 (題目連接)php
$(n+1)*(n+1)$的網格圖上,相鄰兩點間有一些人流。左上角點的海拔$0$,右下角海拔$1$,沒單位人流從海拔低的地方走到海拔高的地方會消耗對應的體力。問最少消耗多少體力。ios
最小割很顯然,轉爲對偶圖跑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; }