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

来源:互联网 发布:红包源码 编辑:程序博客网 时间:2024/05/21 18:41

这道题作为一道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;}


0 0
原创粉丝点击