【 UVALive - 5095】Transportation(费用流)

时间:2023-03-08 15:44:09
【 UVALive - 5095】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 ∗ x
2 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 ≤ N ≤ 100, 1 ≤ M ≤ 5000,
0 ≤ K ≤ 100). 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 ≤ ui
, vi ≤ N,
0 < ai ≤ 100, Ci ≤ 5)

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

【分析】

  此题要拆边。(容量较小)

  对于一个费用系数为a,容量为5的边拆成5条容量为1,费用依次为1a,3a,5a,7a,9a的边。

  因为求的是最小费用流,如果这条弧的流量为1,走的肯定是1a;如果流量为2,走的肯定是1a,3a这两条,如果流量为3,走的肯定是1a,3a,5a……不难验证,不管流量是1~5之间的哪一个,相应流量选取的边的费用之和恰好就是未拆边是的相应费用。

  这样问题就转化成普通的最小费用最大流问题了。(当流量到达k即可break)

  费用流大概是这样做的:

  每次找费用最小的增广路走,走到走不完为止。所以最终ans是最大流前提下最小费用。

代码如下:

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define Maxn 110
#define Maxm 5100
#define INF 0xfffffff int n,m,k; struct node
{
int x,y,f,c,o,next;
}t[Maxm*];int len;
int first[Maxn];
int flow[Maxn],dis[Maxn],pre[Maxn];
bool inq[Maxn]; int mymin(int x,int y) {return x<y?x:y;} void ins(int x,int y,int f,int c)
{
t[++len].x=x;t[len].y=y;t[len].f=f;t[len].c=c;
t[len].next=first[x];first[x]=len;t[len].o=len+;
t[++len].x=y;t[len].y=x;t[len].f=;t[len].c=-c;
t[len].next=first[y];first[y]=len;t[len].o=len-;
} queue<int > q;
bool BFS(int f1,int f2)
{
while(!q.empty()) q.pop();
memset(pre,-,sizeof(pre));
memset(inq,,sizeof(inq));
memset(dis,,sizeof(dis));
pre[f1]=;flow[f1]=INF;inq[f1]=;
dis[f1]=;q.push(f1);
while(!q.empty())
{
int x=q.front(),y,i;
for(i=first[x];i;i=t[i].next) if(t[i].f>)
{
y=t[i].y;
if(dis[y]>dis[x]+t[i].c)
{
pre[y]=i;
dis[y]=dis[x]+t[i].c;
flow[y]=mymin(t[i].f,flow[x]);
if(!inq[y]) {q.push(y);inq[y]=;}
}
}
q.pop();inq[x]=;
}
if(pre[f2]==-) return ;
return flow[f2];
} void max_flow(int x,int y)
{
int a,sum=,h=;
bool ok=;
while(a=BFS(x,y))
{
int now=y;sum+=a*dis[y];
h+=a;
while(now!=x)
{
t[pre[now]].f-=a;
t[t[pre[now]].o].f+=a;
now=t[pre[now]].x;
}
if(h>=k) break;
}
if(h<k) printf("-1\n");
else printf("%d\n",sum);
} int main()
{
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
len=;
memset(first,,sizeof(first));
for(int i=;i<=m;i++)
{
int x,y,z,kk,now=;
scanf("%d%d%d%d",&x,&y,&z,&kk);
for(int i=;i<=kk;i++)
{
ins(x,y,,z*(i*i-now));
now+=i*i-now;
}
}
max_flow(,n);
}
return ;
}

[LA5095]

2016-05-23 13:39:41