http://www.lydsy.com/JudgeOnline/problem.php?id=2007 (题目链接)
题意
$(n+1)*(n+1)$的网格图上,相邻两点间有一些人流。左上角点的海拔$0$,右下角海拔$1$,没单位人流从海拔低的地方走到海拔高的地方会消耗对应的体力。问最少消耗多少体力。
Solution
最小割很显然,转为对偶图跑Dijkstra就好了。
用pair写个堆各种奇怪的错误是smg,建图还建错了,今天晚上不适合写题= =
细节
priority_queue默认大根堆= =。
代码
// 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; }