• POJ


    题目链接:http://poj.org/problem?id=2135

    今天学习最小费用流。模板手敲了一遍。

    产生了一个新的问题:对于一条无向边,这样修改了正向边容量后,反向边不用管吗?

    后来想了想,得出了个结论。路径所选的边只会包括正反中的一条。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <queue>
    #include <algorithm>
    using namespace std;
    const int maxn = 2e3;
    const int INF = 1e9;
    int dist[maxn];
    int pv[maxn],pe[maxn];
    struct edge
    {
        int to, cap, rev;
        int cost;
        edge(int a, int b, int c, int d)
        {
            to = a, cap = b, cost = c, rev = d;
        }
    };
    vector<edge> g[maxn];
    void addedge(int from,int to,int cap,int cost)
    {
        g[from].push_back(edge(to,cap,cost,g[to].size()));
        g[to].push_back(edge(from,0,-cost,g[from].size()-1));
    }
    int n;
    int vis[maxn];
    void SPFA(int s, int t)
    {
        for(int i = 1; i < maxn; i++) dist[i] = INF;
        memset(vis, 0, sizeof(vis));
        dist[s] = 0, vis[s] = 1;
        queue<int> q;
        q.push(s);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = 0;
            for(int i = 0; i < g[u].size(); i++)
            {
                edge &e = g[u][i];
                if(e.cap > 0 && (dist[e.to] - (dist[u] + e.cost)) > 0)
                {
                    pv[e.to] = u, pe[e.to] = i;
                    dist[e.to] = dist[u] + e.cost;
                    if(!vis[e.to])
                    {
                        vis[e.to] = 1;
                        q.push(e.to);
                    }
                }
            }
        }
    }
    int min_cost_flow(int s,int t,int f,int& max_flow)
    {
        int ret = 0.0;
        while(f>0)
        {
            SPFA(s, t);
            if(dist[t] == INF) return ret;///同一目的地,每次增广路都是最小费用
            ///当所有边的流量都流净后,即没有残余网络,返回。
            int d = f;
            for(int v=t;v!=s;v=pv[v])
            {
                d = min(d,g[pv[v]][pe[v]].cap);
            }
            f -= d;
            max_flow += d;
            ret += (int)d*dist[t]; ///走一单位就消耗dist[t]
            for(int v=t;v!=s;v=pv[v])
            {
                edge &e = g[pv[v]][pe[v]];
                e.cap -= d;
                g[v][e.rev].cap += d;
            }
        }
        return ret;
    }
    int main()
    {
        int n,m;
        scanf("%d %d",&n,&m);
        int s=0,t=n+1;
        addedge(s,1,2,0);
        addedge(n,t,2,0);
        for(int i=1;i<=m;i++)
        {
            int x,y,w;
            scanf("%d %d %d",&x,&y,&w);
            addedge(x,y,1,w);
            addedge(y,x,1,w);
        }
       // printf("%d
    ",e[6].cap);
       ///反向边不用管它,因为路径只会选择正反里面的一条边
        int maxflow = 0;
        int ans = min_cost_flow(s,t,INF,maxflow);
        for(int i = 0; i < maxn; i++) g[i].clear();
        printf("%d
    ",ans);
        return 0;
    }
    Code
  • 相关阅读:
    iOS 11和xcode9
    #ifdef __OBJC__宏定义的作用
    项目小分析------从 优普钱包工资单 谈代码的规范性和界面的一般写法
    UIAlertView 点击按钮后控制其是否消失
    iOS 限制输入字数完美解决方案
    tn文本分析语言(四) 实现自然语言计算器
    重磅开源:TN文本分析语言
    差一点其实差很多
    光棍节之夜,用数据分析帮女神学姐选婚房
    你能排第几?2016互联网行业薪酬数据分析
  • 原文地址:https://www.cnblogs.com/littlepear/p/7611880.html
Copyright © 2020-2023  润新知