BZOJ 1001 对偶图最短路=最小割

来源:互联网 发布:微信营销好还是淘宝好 编辑:程序博客网 时间:2024/05/06 09:10

点数有1e6,所以一般的最大流算法会超时,转换成求对偶图上的最短路来处理。注意N,M为1时候特判下。这里用SPFA求最短路。
具体点:
把原图的起点和终点连接起来,外平面被分成了两块,对应对偶图中的起点和终点来求最短路即可。

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <cstring>#include <vector>#include <map>#include <queue>#define INF 0x3f3f3f3fusing namespace std;typedef long long LL;const int maxn=3000010;struct Edge{    int v;    int cost;    Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}};vector<Edge>E[maxn];void addedge(int u,int v,int w){    //cout<<u<<"----"<<v<<"-----"<<w<<endl;    E[u].push_back(Edge(v,w));    E[v].push_back(Edge(u,w));}bool vis[maxn];int cnt[maxn];int dist[maxn];bool SPFA(int start,int n){    memset(vis,0,sizeof(vis));    memset(cnt,0,sizeof(cnt));    for(int i=0;i<=n;i++)dist[i]=INF;    vis[start]=1;    dist[start]=0;    queue<int>que;    while(!que.empty())que.pop();    que.push(start);    cnt[start]=1;    while(!que.empty()){        int u=que.front();        que.pop();        vis[u]=0;        for(int i=0;i<E[u].size();i++){            int v=E[u][i].v;            if(dist[v]>dist[u]+E[u][i].cost){                dist[v]=dist[u]+E[u][i].cost;                if(!vis[v]){                    vis[v]=1;                    que.push(v);                    if(++cnt[v]>n)return 0;                }            }        }    }    return 1;}int N,M,s,t,w;int main(){    scanf("%d%d",&N,&M);    if(N==1||M==1){        int x=N+M-2;        int ans=INF;        for(int i=1;i<x;i++){            scanf("%d",&w);            ans=min(ans,w);        }        printf("%d\n",ans);        return 0;    }    int t=2*(N-1)*(M-1)+1;    for(int i=1;i<=N;i++){        for(int j=1;j<=M-1;j++){            scanf("%d",&w);            if(i==1){                addedge(2*j,t,w);            }            else if(i==N){                addedge(0,(i-2)*2*(M-1)+2*j-1,w);            }            else {                addedge((i-2)*2*(M-1)+2*j-1,(i-1)*2*(M-1)+2*j,w);            }        }    }    for(int i=1;i<=N-1;i++){        for(int j=1;j<=M;j++){        scanf("%d",&w);        if(j==1){            addedge(0,1+(i-1)*(M-1)*2,w);        }        else if(j==M){            addedge(i*(M-1)*2,t,w);        }        else {            addedge((j-1)*2+(i-1)*2*(M-1),(j-1)*2+(i-1)*2*(M-1)+1,w);        }        }    }    int k=0;    for(int i=1;i<=N-1;i++){        for(int j=1;j<=M-1;j++){            scanf("%d",&w);            addedge(k*2+1,k*2+2,w);            k++;        }    }    SPFA(0,t);    printf("%d\n",dist[t]);    return 0;}
0 0