hdoj 3667 Transportation

来源:互联网 发布:mysql exists 代替 in 编辑:程序博客网 时间:2024/05/24 06:15

类型:最小费用流

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3667

来源:2010 Asia Regional Harbin

思路:对于每条边,不同流量的费用不同,可以将其拆边:对于容量为x的边,拆成x条容量为1的边,费用分别为1,3, 5,7....(2 * x - 1)。

第i次取该路时,费用为a * (2 * i - 1),此时流量为i,总费用为a * i ^ 2。求最小费用最大流。构造超级源点,流量为K,费用为0,用来判断解的存在性。

由于:n^2 = 1 + 3 + 5 + ... + (2 * n - 1)

// hdoj 3667 Transportation// wa wa ac 468MS 872K#include <cstdio>#include <cstring>#include <iostream>#include <queue>#include <algorithm>using namespace std;#define FOR(i,a,b) for(i = (a); i < (b); ++i)#define FORE(i,a,b) for(i = (a); i <= (b); ++i)#define FORD(i,a,b) for(i = (a); i > (b); --i)#define FORDE(i,a,b) for(i = (a); i >= (b); --i)#define CLR(a,b) memset(a,b,sizeof(a))const int INF = 0x7f7f7f7f;const int MAXN = 1010;const int MAXM = 200000;struct {    int v, cap, a, cost, nxt;}edge[MAXM];int n, m, ans, maxf, k, K;int pre[MAXN], dis[MAXN], head[MAXN];bool vis[MAXN];void addedge(int u,int v, int ca, int co) {    edge[k].v = v;    edge[k].cap = ca;    edge[k].cost = co;    edge[k].nxt = head[u];    head[u] = k++;    edge[k].v = u;    edge[k].cap = 0;    edge[k].cost = -co;    edge[k].nxt = head[v];    head[v] = k++;}bool spfa(int x) {    int i;    FORE(i, 0, n + 1)        dis[i] = INF;    CLR(vis, false);    CLR(pre, 0);    dis[x] = 0;    queue<int> q;    q.push(x);    vis[x] = true;    while(!q.empty()) {        int u = q.front();        q.pop();        vis[u] = false;        for(i = head[u]; i != -1; i = edge[i].nxt){            int v = edge[i].v;            if(edge[i].cap > 0 && dis[v] > dis[u] + edge[i].cost) {                dis[v] = dis[u] + edge[i].cost;                pre[v] = i;                if(!vis[v]){                    vis[v] = true;                    q.push(v);                }            }        }    }    if(dis[n] == INF)        return false;    return true;}void end() {    int u, p, a = INF;    u = n;    while(u != 0) {        p = pre[u];        a = min(a, edge[p].cap);        u = edge[p ^ 1].v;    }    for(u = n; u != 0; u = edge[p ^ 1].v) {        p = pre[u];        edge[p].cap -= a;        edge[p ^ 1].cap += a;    }    ans += dis[n] * a;    maxf += a;}void init() {    int i, j;    int u, v, a, c;    k = 2;    maxf = ans = 0;    CLR(head, -1);    addedge(0, 1, K, 0);    FORE(i, 1, m) {        scanf("%d %d %d %d", &u, &v, &a, &c);        FORE(j, 1, c)            addedge(u, v, 1, a * (2 * j - 1));    }}int main() {    while(scanf("%d %d %d", &n, &m, &K) != EOF) {        init();        while(spfa(0)) {            end();        }        if(maxf < K)            printf("-1\n");        else            printf("%d\n", ans);    }    return 0;}


原创粉丝点击