[BeiJing2006]狼抓兔子 平面图最小割
挺有意思的结论,对偶图中的一个环对应原图中一种割,把边流量转为距离跑最短路就是最小割了
//#include<bits/stdc++.h> //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; const double pi=acos(-1.0); #define ll long long #define pb push_back #define sqr(a) ((a)*(a)) #define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)) const double eps=1e-10; const int maxn=2e6+56; const int inf=0x3f3f3f3f; const int mod=1e9+7; int n,m; int from,to; struct EDGE{int v,w;}; vector<EDGE>G[maxn]; void addedge(int u,int v,int w){ G[u].pb((EDGE){v,w}); G[v].pb((EDGE){u,w}); } struct NODE{ int v,d; friend bool operator<(NODE a,NODE b){return a.d>b.d;} }; int d[maxn],vis[maxn]; void dij(int from,int to){ for(int i=0;i<maxn;i++)d[i]=inf; d[from]=0; priority_queue<NODE>Q; NODE now=(NODE){from,0}; Q.push(now); while(!Q.empty()){ NODE now=Q.top();Q.pop(); int u=now.v; if(vis[u])continue; vis[u]=1; for(int i=0;i<G[u].size();i++){ if(d[G[u][i].v]>d[u]+G[u][i].w){ d[G[u][i].v]=d[u]+G[u][i].w; NODE nxt=(NODE){G[u][i].v,d[G[u][i].v]}; Q.push(nxt); } } } printf("%d\n",d[to]); } int main(){ while(~scanf("%d%d",&n,&m)){ from=0;to=2*(n-1)*(m-1)+1; int x,y,cost; for(int i=1;i<=n;i++){ for(int j=1;j<m;j++){ scanf("%d",&cost); x=i==1?from:(2*(i-1)-1)*(m-1)+j; y=i==n?to:(2*(i-1))*(m-1)+j; addedge(x,y,cost); } } for(int i=1;i<n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&cost); x=j==1?to:(2*(i-1))*(m-1)+j-1; y=j==m?from:(2*(i-1))*(m-1)+j-1+m; addedge(x,y,cost); } } for(int i=1;i<n;i++){ for(int j=1;j<m;j++){ scanf("%d",&cost); x=(2*(i-1))*(m-1)+j; y=(2*(i-1)+1)*(m-1)+j; addedge(x,y,cost); } } dij(from,to); } }