上下界费用流

CodeForces 708D Incorrect Flow

这是道可行流最小费用的题目,这题好神奇。

看这老哥的题解就ok了。戳这

我觉得他少说了一条边,但代码中却体现了,就是一条流量为$(f,f)$的边,费用为0,就是固定流量的一条边。

 还要注意一点是,$f>c$的时候,$f$往下调到$c$以下时,$c$是不动的。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200;
const int INF = 1e9;
int dist[maxn];
int pv[maxn],pe[maxn];
struct edge
{
    int to, cap, pre;
    int cost;
}e[1450];
int tot = 0, head[maxn];
void init(int n)
{
    tot = 0;
    fill(head, head + n + 1, -1);
}
void add(int from,int to,int cap, int cost)
{
    e[tot].pre = head[from];
    e[tot].to = to;
    e[tot].cap = cap;
    e[tot].cost = cost;
    head[from] = tot++;
}
void addedge(int from,int to,int cap, int cost)
{
    add(from,to,cap,cost);
    add(to,from,0,-cost);
}
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 = head[u]; ~i; i = e[i].pre)
        {
            int to = e[i].to, cap = e[i].cap;
            if(cap > 0 && (dist[to] - (dist[u] + e[i].cost)) > 0)
            {
                pv[to] = u, pe[to] = i;
                dist[to] = dist[u] + e[i].cost;
                if(!vis[to])
                {
                    vis[to] = 1;
                    q.push(to);
                }
            }
        }
    }
}
int min_cost_flow(int s,int t,int f,int& max_flow)
{
    int ret = 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, e[pe[v]].cap);
        }
        f -= d;
        max_flow += d;
        ret += (int)d*dist[t]; ///走一单位就消耗dist[t]
        for(int v=t;v!=s;v=pv[v])
        {
            e[pe[v]].cap -= d;
            e[pe[v]^1].cap += d;
        }
    }
    return ret;
}


int d[maxn];

int main()
{
    int n, m; scanf("%d %d", &n, &m);
    int u, v, c, f;
    init(n + 4);
    int ans = 0;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d %d %d", &u, &v, &c, &f);
        d[u] -= f;
        d[v] += f;
        if(c >= f)
        {
            addedge(u, v, c - f, 1);
            addedge(u, v, INF, 2);
            addedge(v, u, f, 1);
        }
        else
        {
            ans += f - c;
            addedge(v, u, f - c, 0);
            addedge(u, v, INF, 2);
            addedge(v, u, c, 1);///c不用往下调啊啊啊
        }
    }
    addedge(n, 1, INF, 0);
    int Ss = n + 1, Tt = n + 2;
    for(int i = 1; i <= n; i++)
    {
        if(d[i] > 0) addedge(Ss, i, d[i], 0);
        if(d[i] < 0) addedge(i, Tt, -d[i], 0);
    }
    int max_flow = 0;
    ans += min_cost_flow(Ss, Tt, INF, max_flow);
    printf("%d\n", ans);
    return 0;
}
Code

 

posted @ 2018-10-26 15:10  汪汪鱼  阅读(279)  评论(0编辑  收藏  举报