平面图最大流
建出对偶图,最短路即最大流
连接s,t形成的面为新的s,外围都是新的t,
有向图连边方向视情况而定
#include<cstdio> #include<cstring> #include<queue> #define LL long long #define INF 1000000000 using namespace std; LL dis[500000]; int b[500000]; int next[5000000],des[5000000],cnt=0,nd[500000],n; LL len[5000000]; struct data{ int num; LL dis; bool operator <(const data &a)const { return (a.dis<dis); } }; priority_queue <data> heap; void addedge(int u,int v,int l){ next[++cnt]=nd[u];nd[u]=cnt; des[cnt]=v;len[cnt]=l; } void build(){ int t; memset(nd,-1,sizeof(nd)); for (int i=1;i<=n+1;i++) for (int j=1;j<=n;j++){ scanf("%d",&t); if (i==1) addedge((i-1)*n+j,n*n+1,t);else if (i==n+1) addedge(0,(i-2)*n+j,t);else addedge((i-1)*n+j,(i-2)*n+j,t); } for (int i=1;i<=n;i++) for (int j=0;j<=n;j++){ scanf("%d",&t); if (j==0) addedge(0,(i-1)*n+j+1,t);else if (j==n) addedge(i*n,n*n+1,t);else addedge((i-1)*n+j,(i-1)*n+j+1,t); } for (int i=1;i<=n+1;i++) for (int j=1;j<=n;j++){ scanf("%d",&t); if (i==1) addedge(n*n+1,(i-1)*n+j,t);else if (i==n+1) addedge((n-1)*n+j,0,t);else addedge((i-2)*n+j,(i-1)*n+j,t); } for (int i=1;i<=n;i++) for (int j=0;j<=n;j++){ scanf("%d",&t); if (j==0) addedge((i-1)*n+j+1,0,t);else if (j==n) addedge(n*n+1,(i-1)*n+j,t);else addedge((i-1)*n+j+1,(i-1)*n+j,t); } } void dij(){ int tcnt; for (int i=0;i<=n*n+1;i++) {data t;t.num=i;t.dis=dis[i];heap.push(t);} while (!heap.empty()){ data t=heap.top(); heap.pop(); if (b[t.num]) continue; for (int p=nd[t.num];p!=-1;p=next[p]) if (dis[des[p]]>dis[t.num]+len[p]){ tcnt++; dis[des[p]]=dis[t.num]+len[p]; data tmp;tmp.num=des[p];tmp.dis=dis[des[p]]; heap.push(tmp); } b[t.num]=1; } } int main(){ scanf("%d",&n); build(); a for (int i=1;i<500000;i++) dis[i]=1000000000; memset(b,0,sizeof(b)); dis[0]=0; dij(); printf("%lld",dis[n*n+1]); }//BZOJ2007