• poj 2135 Farm Tour 最小费用最大流建图跑最短路


    题目链接

    题意:无向图有N(N <= 1000)个节点,M(M <= 10000)条边;从节点1走到节点N再从N走回来,图中不能走同一条边,且图中可能出现重边,问最短距离之和为多少?

    思路:很经典的构图(看题解的);每条原图中的边赋予cap为1,表示只走一次。超级源点s和汇点t分别和起点终点连边,cap为2,这里cap为2就直接限制了只能有两次最大流;同时最大流中以权值限制得到的就是最小费用;很注意的一点就是此题为无向图带权值,建图时每条有向边建成两条即总边数为4*M。由于spfa找最短路是有方向的,所以这样并不会出现一条边找两次的可能;

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string.h>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    #include<stdlib.h>
    #include<time.h>
    #include<stack>
    #include<set>
    #include<map>
    #include<queue>
    using namespace std;
    #define rep0(i,l,r) for(int i = (l);i < (r);i++)
    #define rep1(i,l,r) for(int i = (l);i <= (r);i++)
    #define rep_0(i,r,l) for(int i = (r);i > (l);i--)
    #define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
    #define MS0(a) memset(a,0,sizeof(a))
    #define MS1(a) memset(a,-1,sizeof(a))
    #define MSi(a) memset(a,0x3f,sizeof(a))
    #define inf 0x3f3f3f3f
    #define lson l, m, rt << 1
    #define rson m+1, r, rt << 1|1
    typedef long long ll;
    #define A first
    #define B second
    #define MK make_pair
    typedef __int64 ll;
    template<typename T>
    void read1(T &m)
    {
        T x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        m = x*f;
    }
    template<typename T>
    void read2(T &a,T &b){read1(a);read1(b);}
    template<typename T>
    void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
    template<typename T>
    void out(T a)
    {
        if(a>9) out(a/10);
        putchar(a%10+'0');
    }
    int T,kase = 1,i,j,k,n,m,s,t;
    const int M = 10007;
    int head[M],tot;
    struct Edge{
        int from,to,cap,flow,Next,w;
        Edge(){}
        Edge(int f,int to,int cap,int Next,int w):from(f),to(to),cap(cap),Next(Next),w(w),flow(0){}
    }e[M<<2];
    inline void ins(int u,int v,int w,int cap)
    {
        e[++tot] = Edge{u,v,cap,head[u],w};
        head[u] = tot;
    }
    int d[2007],pre[2007],inq[2007],a[2007];
    bool spfa()
    {
        MSi(d);MS0(inq);
        d[s] = 0;
        queue<int> q;
        q.push(s);
        inq[s] = 1;pre[s] = 0;a[s] = inf;
        while(!q.empty()){
            int u = q.front();q.pop();
            inq[u] = 0;
            for(int id = head[u];id; id = e[id].Next){
                int v = e[id].to;
                if(d[v] > d[u] + e[id].w && e[id].cap > e[id].flow){
                    d[v] = d[u] + e[id].w;
                    pre[v] = id;
                    a[v] = min(a[u],e[id].cap - e[id].flow);
                    if(!inq[v]){ q.push(v); inq[v] = 1;}
                }
            }
        }
        return d[t] != inf;
    }
    void solve()
    {
        ll ans = 0;
        while(spfa()){
            ans += d[t]*a[t];
            for(int u = t;u != s;u = e[pre[u]].from){
                e[pre[u]].flow += a[t];
                e[pre[u]^1].flow -= a[t];
            }
        }
        printf("%I64d
    ",ans);
    }
    int main()
    {
        while(scanf("%d%d",&n,&m) == 2){
            MS0(head);tot = 1;
            s = 0,t = n+1;
            int u,v,w;
            rep0(i,0,m){
                read3(u,v,w);
                ins(u,v,w,1);ins(v,u,-w,0);// ** 下面不能省略,因为是无向输入的.
                ins(v,u,w,1);ins(u,v,-w,0); 
            }
            ins(s,1,0,2);ins(1,s,0,0);
            ins(n,t,0,2);ins(t,n,0,0);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    webapi Action中跳转到指定内容
    命令行添加防火墙入站规则
    nps简单配置(linux环境)
    C# 执行Javascript脚本
    Docker集群管理(Docker Swarm)
    linux简单的部署frp
    QMap只有insert,而没有append
    SqlServer 数据发布与订阅时一个小问题的处理
    Vue 内部指令缩写
    html中ol li和ul li的区别
  • 原文地址:https://www.cnblogs.com/hxer/p/5353222.html
Copyright © 2020-2023  润新知