[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的边求最短路

#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
",dis[t]);
    return 0;
}
View Code

     

原文地址:https://www.cnblogs.com/starve/p/13307752.html