您的位置:首页 > 运维架构

UVa #1349 Optimal Bus Route Design (例题11-10)

2015-03-29 23:21 465 查看
这道题作为一道regional,最值得学习的应该是问题的等价转换。

把“找出几个圈,使得所有的点都只存在于一个圈内”,转换为“给每个点找一个孩子,使得一个点只有一个父亲”。转换后的问题,就可以用二分图匹配来做了:每个点拆成两部分分别放在二分图的S和T,使得S到T的连线代表儿子-父亲的关系。之后再求二分图的带权值的完美匹配,则可以保证每个结点只有一个儿子、一个父亲的情况下,求出最小费用了。

我自己想的时候就只考虑了从“画圈”上来下手的方法,但是都很麻烦,而且效率不高。通过探索“圆圈”的特性(每个结点只有一个儿子、一个父亲),则可以将问题转换、建模成可以用经典模型解决的问题,这种思路应该多学习和锻炼~

Run Time: 0.146s

#define UVa  "LT11-10.1349.cpp"		//Optimal Bus Route Design

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<iostream>

using namespace std;

//Global Variables.
const int maxn = 100 + 5, INF = 1<<30;
int n;
////

struct Edge {
    int from, to, cap, flow, cost;
    Edge(int f, int t, int c, int fw, int ct): from(f), to(t), cap(c), flow(fw), cost(ct) {}
};

struct MCMF {
    vector<Edge> edges;
    vector<int> G[2*maxn];
    int a[2*maxn], p[2*maxn], d[2*maxn], inq[2*maxn];

    void init() {
        edges.clear();
        for(int i = 0; i < 2*maxn; i ++)G[i].clear();
    }
    void addEdge(int from, int to, int cap, int flow, int cost) {
        edges.push_back(Edge(from, to, cap, flow, cost));
        edges.push_back(Edge(to, from, 0, flow, -cost));
        G[from].push_back(edges.size() - 2);
        G[to].push_back(edges.size() - 1);
    }
    bool bellmanFord(int src, int targ, int& flow, long long& cost) {
        for(int i = 0; i <= 2*maxn; i ++) d[i] = INF;
        memset(inq, 0, sizeof(inq));
        queue<int> q;
        q.push(src);
        inq[src] = 1;
        a[src] = INF;
        d[src] = 0;
        p[src] = 0;
        while(!q.empty()) {
            int x = q.front(); q.pop();
            inq[x] = 0;
            for(int i = 0; i < G[x].size(); i ++) {
                Edge& e = edges[G[x][i]];
                int y = e.to;
                if(e.cap > e.flow && d[y] > d[x] + e.cost) {
                    d[y] = d[x] + e.cost;
                    a[y] = min(a[x], e.cap-e.flow);
                    p[y] = G[x][i];
                    if(!inq[y]) {
                        inq[y] = 1;
                        q.push(y);
                    }
                }
            }
        }
        if(d[targ] == INF) return false;
        for(int u = targ; u != src; u = edges[p[u]].from) {
            edges[p[u]].flow += a[targ];
            edges[p[u]^1].flow -= a[targ];
        }
        flow += a[targ];
        cost += (long long)d[targ]*(long long)a[targ];
        return true;
    }

    void mincostMaxflow(int src, int targ, int& flow, long long& cost) {
        flow = cost = 0;
        while(bellmanFord(src, targ, flow, cost));
    }
}mcmf;

int main() {
    while(cin>>n && n) {
        mcmf.init();
        for(int from = 1; from <= n; from ++) {
            int to, cost;
            while(cin>>to && to) {
                to += n;
                cin>>cost;
                mcmf.addEdge(from, to, 1, 0, cost);
            }
        }
        int src = 2*n+1, targ = 2*n+2;
        for(int i = 1; i <= n; i ++) {
            mcmf.addEdge(src, i, 1, 0, 0);
            mcmf.addEdge(i+n, targ, 1, 0, 0);
        }
        int flow;
        long long cost;
        mcmf.mincostMaxflow(src, targ, flow, cost);
        if(flow == n)
            printf("%lld\n",cost);
        else
            printf("N\n");

    }

    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: