您的位置:首页 > 其它

uva 1486 Transportation (费用流+拆边)

2015-08-09 16:55 260 查看

uva 1486 Transportation

Description

There are N cities, and M directed roads connecting them. Now you want to transport K units of goods from city 1 to city N. There are many robbers on the road, so you must be very careful. The more goods you carry, the more dangerous it is. To be more specific, for each road i, there is a coefficient ai. If you want to carry x units of goods along this road, you should pay ai*x2 dollars to hire guards to protect your goods. And what’s worse, for each road i, there is an upper bound Ci, which means that you cannot transport more than Ci units of goods along this road. Please note you can only carry integral unit of goods along each road.

You should find out the minimum cost to transport all the goods safely.

Input

There are several test cases. The first line of each case contains three integers, N, M and K. (1≤ \leN≤ \le100, 1≤ \leM≤ \le5000, 0≤ \leK≤ \le100). Then M lines followed, each contains four integers (ui, vi, ai, Ci), indicating there is a directed road from city ui to vi, whose coefficient is ai and upper bound is Ci. (1≤ \leui, vi≤ \leN, 0 < ai≤ \le100, Ci≤ \le5)

Output

Output one line for each test case, indicating the minimum cost. If it is impossible to transport all the K units of goods, output `-1’.

Sample Input

2 1 2

1 2 1 2

2 1 2

1 2 1 1

2 2 2

1 2 1 2

1 2 2 2

Sample Output

4

-1

3

题目大意:某国有n(n<=100n<=100)座城市,由m(m<=5000m<=5000)条单向道路相连。你希望从城市1运送k(k<=100k<=100)单位货物到城市n,这些道路并不安全,有很多强盗,所以你需要雇佣镖师来做护卫。每条道路都有一个危险系数ai(ai<=100ai<=100),如果你带着x个单位的货物通过,需要给镖师ai∗x2ai*x^2的佣金,镖师才会保证你的安全。每条道路都有一个限制,最多能运送Ci(Ci<=5Ci<=5)的货物。现在问,在能完成运送x个单位的货物到n号城市的情况下最小的花费,如果送不到,则输出-1。

解题思路:如果不进行拆边的话,每条道路的费用是动态变化的,所以我们要进行拆边,使得每条道路的费用固定。假如一条边的危险系数是a,最多能运送的货物为C,那么这条边就可以C条边每条边的费用为a∗(i2−(i−1)2)a*(i^2 - (i - 1)^2),i从1到C,容量为1。这样拆出来的边总费用为a∗C2a*C^2,总容量为C。拆完边,建完图,跑一发最小费。

[code]#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <queue>
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 200;
const int M = 150000;
typedef long long ll;
int n, m, k, s, t;
int pre
, inq
; 
ll a
, d
;
struct Edge{
    int from, to;
    ll cap, flow;
    ll cos;
};

vector<Edge> edges;
vector<int> G[M];

void init() {
    for (int i = 0; i < M; i++) G[i].clear();
    edges.clear();
}

void addEdge(int from, int to, ll cap, ll flow, ll cos) {
    edges.push_back((Edge){from, to, cap, 0, cos});
    edges.push_back((Edge){to, from, 0, 0, -cos});
    int m = edges.size();
    G[from].push_back(m - 2); G[to].push_back(m - 1);
}

int BF(int s, int t, ll& flow, ll& cost) {
    queue<int> Q;
    memset(inq, 0, sizeof(inq));
    memset(a, 0, sizeof(a));
    memset(pre, 0, sizeof(pre));
    for (int i = 0; i < N; i++) d[i] = INF;
    d[s] = 0;
    a[s] = INF;
    inq[s] = 1;
    int flag = 1;
    pre[s] = 0;
    Q.push(s);
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        inq[u] = 0;
        for (int i = 0; i < G[u].size(); i++) {
            Edge &e = edges[G[u][i]];
            if (e.cap > e.flow && d[e.to] > d[u] + e.cos) {
                d[e.to] = d[u] + e.cos;
                a[e.to] = min(a[u], e.cap - e.flow);
                pre[e.to] = G[u][i];
                if (!inq[e.to]) {
                    inq[e.to] = 1;
                    Q.push(e.to);
                }
            }   
        }
        flag = 0;
    }
    if (d[t] == INF) return 0;
    flow += a[t];
    cost += (ll)d[t] * (ll)a[t];
    for (int u = t; u != s; u = edges[pre[u]].from) {
        edges[pre[u]].flow += a[t];
        edges[pre[u]^1].flow -= a[t];
    }
    return 1;
}

int MCMF(int s, int t, ll& cost) {
    ll flow = 0;
    cost = 0;       
    while (BF(s, t, flow, cost));
    return flow;
}

void input() {
    int u, v;
    ll a;
    ll c;
    for (int i = 0; i < m; i++) {
        scanf("%d %d %lld %lld", &u, &v, &a, &c);
        for (int i = 1; i <= c; i++) {
            addEdge(u, v, 1, 0, a * (i * i - (i - 1) * (i - 1)));   
        }
    }
    addEdge(0, 1, k, 0, 0);
    s = 0, t = n;
}

int main() {
    while (scanf("%d %d %d", &n, &m, &k) == 3) {
        init();
        input();    
        ll cost;    
        if (MCMF(s, t, cost) != k) printf("-1\n");
        else printf("%lld\n", cost);
    }   
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: