[ICPC-Beijing 2006]狼抓兔子(对偶图)
对偶图学习:https://blog.csdn.net/MaxMercer/article/details/77976666
https://blog.csdn.net/MaxMercer/article/details/77977447
题:https://www.luogu.com.cn/problem/P4001
题意:网格图求最小割
分析:源点和汇点连边转化为对偶图,再在对偶图上去掉s到t的边求最短路
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; inline void read(int &x) { x = 0; char c = getchar(); while(!isdigit(c)) c = getchar(); while(isdigit(c)) x = x * 10 + c - '0', c = getchar(); } const int M=2e6+10; const int inf=0x3f3f3f3f; typedef long long ll; #define pb push_back int dis[M]; bool vis[M]; struct node{ int v,c; node(int V=0,int C=0):v(V),c(C){} bool operator <(const node &b)const { return c>b.c; } }; struct Edge{ int v,cost; Edge(int V=0,int Cost=0):v(V),cost(Cost){} }; vector<Edge>g[M]; void addedge(int u,int v,int w){ g[u].push_back(Edge(v,w)); g[v].push_back(Edge(u,w)); } void dij(int st,int n){ priority_queue<node>que; memset(dis,0x3f,sizeof(dis)); while(!que.empty())que.pop(); dis[st]=0; que.push(node(st,0)); while(!que.empty()){ node tmp=que.top(); que.pop(); int u=tmp.v; if(vis[u]) continue; vis[u]=true; for(auto it:g[u]){ int v=it.v; int cost=it.cost; if(!vis[v]&&dis[v]>dis[u]+cost){ dis[v]=dis[u]+cost; que.push(node(v,dis[v])); } } } } int main(){ int n,m; read(n),read(m); int s=(n-1)*(m-1)*2+1; int t=s+1; int nowi=2,nowj=1; int x; for(int i=1;i<=n;i++){ for(int j=1;j<=m-1;j++){ read(x); if(i==1) addedge(nowi,t,x),nowi+=2; else if(i<n) addedge(nowi,nowj,x),nowi+=2,nowj+=2; else addedge(s,nowj,x),nowj+=2; } } nowi=2,nowj=1; for(int i=1;i<=n-1;i++){ for(int j=1;j<=m;j++){ read(x); if(j==1) addedge(nowj,s,x),nowj+=2; else if(j<m) addedge(nowj,nowi,x),nowi+=2,nowj+=2; else addedge(nowi,t,x),nowi+=2; } } nowi=2,nowj=1; for(int i=1;i<=n-1;i++){ for(int j=1;j<=m-1;j++){ read(x); addedge(nowi,nowj,x),nowi+=2,nowj+=2; } } dij(s,t); printf("%d\n",dis[t]); return 0; }