UVALive-5095 Transportation (最小费用流+拆边)

题目大意:有n个点,m条单向边。要运k单位货物从1到n,但是每条道路上都有一个参数ai,表示经这条路运送x个单位货物需要花费ai*x*x个单位的钱。求最小费用。

题目分析:拆边。例如:u到v的容量为5,则拆成容量均为1,单位费用分别为1,3,5,7,9的5条边。求流恰好能满足运输需求时的最小费用即可。

代码如下:

# include<iostream>
# include<cstdio>
# include<cmath>
# include<string>
# include<vector>
# include<list>
# include<set>
# include<map>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;

# define LL long long
# define REP(i,s,n) for(int i=s;i<n;++i)
# define CL(a,b) memset(a,b,sizeof(a))
# define CLL(a,b,n) fill(a,a+n,b)

const double inf=1e30;
const int INF=1<<30;
const int N=5005;

int k;

struct Edge
{
    int fr,to,cap,fw,cost;
    Edge(int fr,int to,int cap,int fw,int cost){
        this->fr=fr;
        this->to=to;
        this->cap=cap;
        this->fw=fw;
        this->cost=cost;
    }
};
struct MCMF
{
    vector<Edge>edges;
    vector<int>G[N];
    int s,t,n;
    int inq[N];
    int p[N];
    int a[N];
    int d[N];

    void init(int n,int s,int t)
    {
        this->n=n;
        this->s=s,this->t=t;
        for(int i=0;i<n;++i) G[i].clear();
        edges.clear();
    }

    void addEdge(int u,int v,int cap,int cost)
    {
        edges.push_back(Edge(u,v,cap,0,cost));
        edges.push_back(Edge(v,u,0,0,-cost));
        int m=edges.size();
        G[u].push_back(m-2);
        G[v].push_back(m-1);
    }

    bool bellmanFord(int &flow,int &cost)
    {
        fill(d,d+n,INF);
        memset(inq,0,sizeof(inq));
        d[s]=0,inq[s]=1,p[s]=0,a[s]=INF;

        queue<int>q;
        q.push(s);
        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]];
                if(e.cap>e.fw&&d[e.to]>d[x]+e.cost){
                    d[e.to]=d[x]+e.cost;
                    p[e.to]=G[x][i];
                    a[e.to]=min(a[x],e.cap-e.fw);
                    if(!inq[e.to]){
                        inq[e.to]=1;
                        q.push(e.to);
                    }
                }
            }
        }
        if(d[t]==INF) return false;
        flow+=a[t];
        cost+=d[t]*a[t];
        for(int u=t;u!=s;u=edges[p[u]].fr){
            edges[p[u]].fw+=a[t];
            edges[p[u]^1].fw-=a[t];
        }
        return true;
    }

    void minCost(int &flow,int &cost)
    {
        flow=cost=0;
        while(bellmanFord(flow,cost))
            if(flow>=k) break;
    }
};
MCMF cf;

int n,m;

int main()
{
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        cf.init(n+1,1,n);
        int a,b,c,d;
        while(m--)
        {
            scanf("%d%d%d%d",&a,&b,&c,&d);
            int cnt=1;
            while(d--)
            {
                cf.addEdge(a,b,1,cnt*c);
                cnt+=2;
            }
        }
        int flow,cost;
        cf.minCost(flow,cost);
        if(flow>=k) printf("%d\n",cost);
        else printf("-1\n");
    }
    return 0;
}

  

时间: 2024-10-26 06:27:34

UVALive-5095 Transportation (最小费用流+拆边)的相关文章

UVALive - 5095 Transportation(拆边+费用流)

题目大意:有n个点,m条边,每条边的容量为ci,费用为ai* x^2(x为流量,ai为所给系数) 现在问能否将k个单位的货物从点1运输到点n,且费用最小 解题思路:拆边,将每条边拆成ci条边,每条边的费用分别为ai * 1, ai * 3, ai * 5-容量都为1,在容量相同的情况下,会选择费用少的流,这样流过的边累加起来的费用刚好为 ai * 流量^2 #include <cstdio> #include <cstring> #include <algorithm>

【 UVALive - 5095】Transportation(费用流)

Description There are N cities, and M directed roads connecting them. Now you want to transport K units ofgoods from city 1 to city N. There are many robbers on the road, so you must be very careful. Themore goods you carry, the more dangerous it is.

hdu3667 Transportation 拆边法+最小费用最大流

/** 题目:hdu3667 Transportation 拆边法+最小费用最大流 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3667 题意:n个城市由m条有向边连接.要从城市1运输k流量到城市n.每条边有可以运输的流量容量,以及费用系数ai. 费用系数指该条边的费用为该条边的运输流量x的平方乘以ai.即ai*x^2. 如果无法运输k流量,输出-1,否则输出从城市1运输k流量到城市n的最小花费. 思路:拆边法+最小费用最大流 假设从u->v 容量为

hdu 3667 拆边加最小费用流

Transportation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2301    Accepted Submission(s): 966 Problem Description There are N cities, and M directed roads connecting them. Now you want to t

uva 1486 Transportation (最大流+拆边)

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,

UVA 1486 - Transportation(网络流+拆边)

UVA 1486 - Transportation 题目链接 题意:一个有向图上运输k货物,有一些边,每个边一个系数a,经过该边如果有x货物,就要缴纳a x x的钱,问运输从1到n最小的代价 思路:费用流,这题边的容量c最大只有5,所以可以拆边,一条边拆成c条边,每条容量1,对应相应的代价为a * (i^2 - (i - 1)^2),然后跑一下费用流即可 代码: #include <cstdio> #include <cstring> #include <vector>

HDU 3667 费用流 拆边 Transportation

题意: 有N个城市,M条有向道路,要从1号城市运送K个货物到N号城市. 每条有向道路<u, v>运送费用和运送量的平方成正比,系数为ai 而且每条路最多运送Ci个货物,求最小费用. 分析: 拆边,每条边拆成费用为a, 3a, 5a的边,这样就能保证每条边的费用和流量的平方成正比. 因为最多运送K个货物,所以增加一个源点和城市1连一条容量为K费用为0的边. 跑一边最小费用最大流,如果满流才有解. 1 #include <iostream> 2 #include <cstdio&

Hdu 3667 Transportation(最小费用流+思路)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3667 思路:平方关系,直接建图每次增广并不是最优.... 1^2=1,2^2=1+3,3^2=1+3+5,4^2=1+3+5+7....... 所以,对于每条边<x,y>,若流量为c,则在x与y之间连c条边,流量均为1,费用分别为a[i],3*a[i],5*a[i].........由于每次增广时流量相同时选择最小花费的边,若该边<x,y>流量为c,则总花费为a[x]+3*a[x]+5

UVaLive 2796 Concert Hall Scheduling (最小费用流)

题意:个著名的音乐厅因为财务状况恶化快要破产,你临危受命,试图通过管理的手段来拯救它,方法之一就是优化演出安排,既聪明的决定接受或拒绝哪些乐团的演出申请,使得音乐厅的收益最大化.该音乐厅有两个完全相同的房间,因此个乐团在申请演出的时候并不会指定房间,你只需要随便分配一个即可.每个演出都会持续若干天,每个房间每天只能举行一场演出.申请数目n为不超过100的正整数,每个申请用3个整数i,j,w来表示,表示从第i天到第j天,愿意支付w元. 析:把每一天都看成是一个结点,然后相邻两天加一个容量为2,费用