UVA1658海军上将,拆点费用流

来源:互联网 发布:淘宝开店客服的子账号 编辑:程序博客网 时间:2024/04/30 04:54

刘汝佳紫书上的题
题意:给n个点m条边的有向加权图,求1->n的两条不重复的路径,使sum权最小
(不重复的路径是指,两条路径没有公共点)

思路见图

这里写图片描述

用的紫书371页的模板

#include<queue>#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long LL;const int N = 20007;const int INF=0x3f3f3f3f;struct MCMF{    struct Edge{        int from,to,cap,flow,cost;        Edge(int x,int y,int z,int u,int v){            from=x;to=y;cap=z;flow=u;cost=v;        }    };    vector <Edge> edges;    vector <int > G[N];    int n,m,inq[N],d[N],p[N],a[N];    inline void Init(int n){        this->n = n;        edges.clear();        for (int i=1;i<=n;i++)G[i].clear();    }    inline void AddEdge(int f,int t,int c,int w){        edges.push_back(Edge(f,t,c,0, w));        edges.push_back(Edge(t,f,0,0,-w));        int top = edges.size();        G[f].push_back(top-2);        G[t].push_back(top-1);    }    bool spfa(int s,int t,int flow,LL &cost){        for (int i=0;i<=n;i++)d[i]=INF;        memset(inq,0,sizeof(inq));        d[s]=0;inq[s]=1;p[s]=0;a[s]=INF;        queue<int>Q;Q.push(s);        for (;!Q.empty();){            int u =Q.front();Q.pop();inq[u]=0;            for (int i=0;i<G[u].size();i++){                Edge &e = edges[G[u][i]];                if (e.cap<=e.flow||d[e.to]<=d[u]+e.cost)continue;                d[e.to] = d[u] + e.cost;                p[e.to] = G[u][i];                a[e.to] = min(a[u],e.cap-e.flow);                if (!inq[e.to]){Q.push(e.to);inq[e.to]=1;}            }        }        if (d[t]==INF)return 0;//false        flow += a[t];        cost +=(LL)d[t]*(LL)a[t];        for (int u=t;u!=s;u=edges[p[u]].from){            edges[p[u]  ].flow += a[t];            edges[p[u]^1].flow -= a[t];        }        return 1;//true    }    //需要保证初始网络中没有负权    int mcmf(int s,int t,LL &cost){        int flow =0; cost = 0;        for (;spfa(s,t,flow,cost););        return flow;    }//MinCostMaxFlow}g;int main(){    //freopen("in.txt","r",stdin);    int x,y,z,n,m;    for (LL ans;~scanf("%d%d",&n,&m);){        g.Init(n<<1);//begin build gragh        for (int i=1;i<=n;i++){            if(i==1||i==n)g.AddEdge(i,i+n,2,0);            else g.AddEdge(i,i+n,1,0);        }        for (;m--;){            scanf("%d%d%d",&x,&y,&z);            g.AddEdge(x+n,y,1,z);        }   //end Build gragh        int flow = g.mcmf(1,n<<1,ans);        printf("%lld\n",ans);    }    return 0;}
0 0
原创粉丝点击