最小费用最大流

CSU 1506 Double Shortest Paths

算是康复福利了,以前没做过,但是实际是非常水的题目,应该可以作为入门题了

诡异的是 这道题description莫名奇妙没了。

题意:
两个人从 1 -> n ,每条路径最多走两次,走第一次为 d ,走第二次为 d+a ,问最短的路径。

思路:
对于一组数据,建两次边即可。容量为1,花费分别为 d , d + a。
源点流入1 容量为 2 , 花费 0
n流入汇点 容量 2 ,花费 0

注: 给定的边为有向边

AC code

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int inf = 99999999;
const int maxn = 1005;
const int maxe = 10005 * 4;

struct MCMF {
private:
    int st, en, idx;
    int head[maxn], dis[maxe], preID[maxe];
    bool vis[maxe];
    queue<int> que;

    struct node {
        int to, next, pre;
        int flow, cost;
        node() {}
        node(int _to, int _next, int _pre, int _flow, int _cost)
            : to(_to)
            , next(_next)
            , pre(_pre)
            , flow(_flow)
            , cost(_cost)
        {
        }
    } edges[maxe];

    bool spfa()
    {
        memset(vis, false, sizeof(vis));
        for (int i = st; i <= en; i++)
            dis[i] = inf;
        vis[st] = true;
        dis[st] = 0;
        que.push(st);
        int u;
        while (!que.empty()) {
            u = que.front();
            que.pop();
            for (int id = head[u]; ~id; id = edges[id].next) {
                int v = edges[id].to;
                if ((edges[id].flow > 0) && (dis[u] + edges[id].cost < dis[v])) {
                    dis[v] = dis[u] + edges[id].cost;
                    preID[v] = id;
                    if (!vis[v]) {
                        vis[v] = true;
                        que.push(v);
                    }
                }
            }
            vis[u] = false;
        }
        return dis[en] != inf;
    }

public:
    void addEdge(int u, int v, int f, int c)
    {
        edges[idx] = node(v, head[u], u, f, c);
        head[u] = idx++;
        edges[idx] = node(u, head[v], v, 0, -c);
        head[v] = idx++;
    }

    void init(int s, int e)
    {
        st = s, en = e;
        memset(head, -1, sizeof head);
        idx = 0;
    }

    int minCost()
    {
        int ans = 0;
        while (spfa()) {
            ans += dis[en];
            for (int id = preID[en]; id != st; id = preID[edges[id].pre]) {
                edges[id].flow--;
                edges[id ^ 1].flow++;
            }
        }
        return ans;
    }
} mcmf;

int main()
{
    int n, m, u, v, c, c1, cas = 0;
    while (scanf("%d %d", &n, &m) != EOF) {
        mcmf.init(0, n + 1);
        mcmf.addEdge(0, 1, 2, 0);
        mcmf.addEdge(n, n + 1, 2, 0);
        while (m--) {
            scanf("%d %d %d %d", &u, &v, &c, &c1);
            mcmf.addEdge(u, v, 1, c);
            mcmf.addEdge(u, v, 1, c + c1);
        }
        printf("Case %d: %d\n", ++cas, mcmf.minCost());
    }
    return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注