• UVA 1658 Admiral 最小费用最大流


    题目链接

        http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51253

    题意:

    给出一个v个点e条边的有向加权图,求1~v的两条不相交的路径使得权值和最小

    题解

    最小费用最大流

    吧2到v-1的每隔结点拆点x和x',中间连一条容量为1费用为0的边,然后求得是1到v流量为2的最小费用流

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int maxn = 1e6+20, M = 30005, mod = 1e9+7, inf = 0x3f3f3f3f;
    typedef long long ll;
    //不同为1,相同为0
    
    const int MAXN = 100000;
    const int MAXM = 1000000;
    const int INF = 0x3f3f3f3f;
    struct Edge
    {
        int to,next,cap,flow,cost;
    }edge[MAXM];
    int head[MAXN],tol;
    int pre[MAXN],dis[MAXN];
    bool vis[MAXN];
    int N;//节点总个数,节点编号从0~N-1
    void init(int n)
    {
        N = n;
        tol = 0;
        memset(head,-1,sizeof(head));
    }
    void add(int u,int v,int cap,int cost)  //点u至点v,容量,花费
    {
        edge[tol].to = v;
        edge[tol].cap = cap;
        edge[tol].cost = cost;
        edge[tol].flow = 0;
        edge[tol].next = head[u];
        head[u] = tol++;
        edge[tol].to = u;
        edge[tol].cap = 0;
        edge[tol].cost = -cost;
        edge[tol].flow = 0;
        edge[tol].next = head[v];
        head[v] = tol++;
    
    
    }
    bool spfa(int s,int t)
    {
        queue<int>q;
        for(int i = 0;i < N;i++)
        {
            dis[i] = INF;
            vis[i] = false;
            pre[i] = -1;
        }
        dis[s] = 0;
        vis[s] = true;
        q.push(s);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = false;
            for(int i = head[u]; i != -1;i = edge[i].next)
            {
                int v = edge[i].to;
                if(edge[i].cap > edge[i].flow &&
                   dis[v] > dis[u] + edge[i].cost )
                {
                    dis[v] = dis[u] + edge[i].cost;
                    pre[v] = i;
                    if(!vis[v])
                    {
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        if(pre[t] == -1)return false;
        else return true;
    }
    //返回的是最大流,cost存的是最小费用
    int minCostMaxflow(int s,int t,int &cost)
    {
        int flow = 0;
        cost = 0;
        while(flow<2&&spfa(s,t))
        {
            int Min = INF;
            for(int i = pre[t];i != -1;i = pre[edge[i^1].to])
            {
                if(Min > edge[i].cap - edge[i].flow)
                    Min = edge[i].cap - edge[i].flow;
            }
            for(int i = pre[t];i != -1;i = pre[edge[i^1].to])
            {
                edge[i].flow += Min;
                edge[i^1].flow -= Min;
                cost += edge[i].cost * Min;
            }
            flow += Min;
        }
        return flow;
    }
    
    
    int main() {
        int n,m;
            while(scanf("%d%d",&n,&m)!=EOF) {
            int S = 0, T = n*2;
            init (5000);
            for(int i=1;i<=m;i++) {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
              if(a!=1&&a!=n)
                add(a+n,b,1,c);
                else add(a,b,1,c);
            }
            add(S,1,2,0);add(n,T,2,0);
            for(int i=2;i<n;i++) add(i,i+n,1,0);
            int ans = 0;
            minCostMaxflow(S,T,ans);
            printf("%d
    ",ans);
            }
    
        return 0;
    }
  • 相关阅读:
    2022年阿里内部Java岗面试offer直通车,年薪50W不是梦
    2022年腾讯首发Java岗分布式面试真题,助力金三银四我是认真的
    open()函数在if条件中时的问题
    关闭stdout后打开stdout
    container_of
    tmpnam函数和tmpfile函数
    dup和dup2函数
    vim命令
    FILE结构体的定义
    jQuery 完整 ajax示例
  • 原文地址:https://www.cnblogs.com/zxhl/p/5308740.html
Copyright © 2020-2023  润新知