Transportation UVALive

来源:互联网 发布:手机淘宝联盟怎么用 编辑:程序博客网 时间:2024/06/04 01:29

Transportation UVALive - 5095

网络流·费用流

题目大意:

某国有n(n<=100)座城市,由m(m<=5000)条单向道路相连。你希望从城市1运送k(0<=k<=100)单位货物到城市n。这些道路并不安全,有很多强盗,所以你决定雇保镖来保护你。每条道路都有一个危险系数ai(0<ai<=100),如果你带着x个单位货物通过,需要给保镖aix2元钱才能保证你的安全(这是合理的,因为带在身边的货物越多越不安全)。另外,每条路上还有一个容量限制CiCi<=5),表示最多只能带Ci个单位的货物通过。注意,货物不能拆开,因此在通过每条边时,身上的货物数量必须是整数。

题解:

拆边。每条边拆成c条,cap=1,cost=1*a、3*a、5*a、7*a、9*a……
这样就满足的费用为aix2的要求。

Code:

#include <iostream>#include <cstdio>#include <cstring>#include <queue>#define D(x) cout<<#x<<" = "<<x<<"  "#define E cout<<endlusing namespace std;const int N = 505;const int M = 1000005;const int INF = 0x3f3f3f3f;int n,m,k,S,T,cost,flow;struct Edge{    int from,to,next,cap,flow,cost;}e[M*2];int head[N],ec=1;void clear(){ memset(head,0,sizeof(head)); ec=1; }void add(int a,int b,int cap,int cost){    ec++; e[ec].from=a; e[ec].to=b;     e[ec].next=head[a]; head[a]=ec;    e[ec].cap=cap; e[ec].flow=0; e[ec].cost=cost;}void add2(int a,int b,int cap,int cost){//  D(a); D(b); D(cap); D(cost); E;    add(a,b,cap,cost); add(b,a,0,-cost);}bool vis[N]; int d[N],pre[N];bool spfa(){    memset(vis,false,sizeof(vis));    memset(d,0x3f,sizeof(d));    queue<int> q; q.push(S); vis[S]=true; d[S]=0;    while(!q.empty()){        int u=q.front(); q.pop(); vis[u]=false;        for(int i=head[u];i;i=e[i].next){            int v=e[i].to;            if(e[i].cap>e[i].flow && d[v]>d[u]+e[i].cost){                d[v]=d[u]+e[i].cost; pre[v]=i;                if(!vis[v]){ vis[v]=true; q.push(v); }            }         }    }    return d[T]!=INF;}void mxf(){    cost=0, flow=0; int a;    while(spfa()){        a=INF;        for(int pos=T,i=pre[T]; pos!=S; pos=e[i].from,i=pre[pos]){            a=min(a,e[i].cap-e[i].flow);        }        for(int pos=T,i=pre[T]; pos!=S; pos=e[i].from,i=pre[pos]){            e[i].flow+=a; e[i^1].flow-=a; cost+=e[i].cost*a;        }        flow+=a;    }}int main(){    freopen("a.in","r",stdin);    while(~scanf("%d%d%d",&n,&m,&k)){        clear();        S=n+1; T=S+1;         add2(S,1,k,0); add2(n,T,k,0);        int u,v,a,c;        for(int i=1;i<=m;i++){            scanf("%d%d%d%d",&u,&v,&a,&c);            for(int i=1;i<=c;i++){                add2(u,v,1,a*(2*i-1));            }        }        mxf();//      D(flow); D(cost); E;        if(flow==k) printf("%d\n",cost);        else puts("-1");    }}
原创粉丝点击