HDU 3667 最小费用最大流+拆边

来源:互联网 发布:成都医疗大数据公司 编辑:程序博客网 时间:2024/05/18 01:13

Transportation

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1599    Accepted Submission(s): 623

 

Problem 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 <= 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

题目大意:要求从点1运输K件货物到点N,每对顶点间的费用为 a*x*x,其中x为该段路的流量,a为一个费用参数。求最小费用。

思路:题目明显是最小费用最大流问题,考虑到每段路的最大流量小于5,则可以将边拆开。比如s->e之间可以运输3件货物,那么将s->e拆成3条边(每条边视作不同的路),流量为1(只能走一次),假如单位费用为a,则该三条边的费用分别为a*1,a*3,a*5,假如该三条路都走了,就相当于直接从s到e运输三件货物,费用为a*3*3 = a*(1 + 3 + 5); 因为在该条路上运输2件货物这个问题上是包含了运输1件货物的,所以如果走了运输量为2件的这条路,潜意思就是运输量为1件的路也走了,所以当添加s->e且数量为2件的时候,费用应该为a*2*2-a*1*1 = 3*a,也就是 a*(n*n)-a*((n-1)*(n-1)) = 2*n - 1.

最后构造一个源点连接到起始点1上,费用为0,流量为K。

View Code
  1 #include <iostream>  2 #include <cstdio>  3 #include <cstring>  4 #include <algorithm>  5 #include <queue>  6 #define INF 0xfffffff  7 #define MAX 105  8   9 using namespace std; 10  11 struct node 12 { 13     int to,val,cost,re,next; 14 }; 15  16 node edge[MAX*1005]; 17 int head[MAX]; 18 int idx; 19  20 int N,M,K; 21  22 int source,sink,pt; 23 int pre[MAX],pos[MAX]; 24 int dis[MAX]; 25 bool inQueue[MAX]; 26  27 void addNode(int from,int to,int val,int cost) 28 { 29     edge[idx].to = to; 30     edge[idx].val = val; 31     edge[idx].cost = cost; 32     edge[idx].re = idx + 1; 33     edge[idx].next = head[from]; 34     head[from] = idx ++; 35     edge[idx].to = from; 36     edge[idx].val = 0; 37     edge[idx].cost = - cost; 38     edge[idx].re = idx - 1; 39     edge[idx].next = head[to]; 40     head[to] = idx ++; 41 } 42  43 bool spfa() 44 { 45     queue <int> Q; 46     for(int i=0; i<=pt; i++) 47     { 48         dis[i] = INF; 49         inQueue[i] = false; 50     } 51     dis[source] = 0; 52     pre[source] = source; 53     Q.push(source); 54     inQueue[source] = true; 55     while(!Q.empty()) 56     { 57         int cur = Q.front(); 58         Q.pop(); 59         inQueue[cur] = false; 60         for(int i=head[cur]; i!=-1; i=edge[i].next) 61         { 62             int to = edge[i].to; 63             if(edge[i].val > 0 && dis[to] > dis[cur] + edge[i].cost) 64             { 65                 dis[to] = dis[cur] + edge[i].cost; 66                 pre[to] = cur; 67                 pos[to] = i; 68                 if(!inQueue[to]) 69                 { 70                     Q.push(to); 71                     inQueue[to] = true; 72                 } 73             } 74         } 75     } 76     if(pre[sink]!=-1 && dis[sink] < INF) 77         return true; 78     return false; 79 } 80  81 int end() 82 { 83     int flow = 0,cost = 0; 84     while(spfa()) 85     { 86         int Min = INF; 87         for(int i=sink; i!=source; i=pre[i]) 88             Min = min(Min,edge[pos[i]].val); 89         flow += Min; 90         cost += Min*dis[sink]; 91         for(int i=sink; i!=source; i=pre[i]) 92         { 93             edge[pos[i]].val -= Min; 94             edge[pos[i]^1].val += Min; 95         } 96     } 97     if(flow < K) 98         return -1; 99     return cost;100 }101 102 int main()103 {104     while(~scanf("%d%d%d",&N,&M,&K))105     {106         idx = 0;107         memset(head,-1,sizeof(head));108         for(int i=1; i<=M; i++)109         {110             int s,e,v,c;111             scanf("%d%d%d%d",&s,&e,&v,&c);112             for(int j=1; j<=c; j++)113                 addNode(s,e,1,v*(2*j-1));114         }115         source = 0;116         sink = N;117         pt = N + 2;118         addNode(source,1,K,0);119         int ans = end();120         printf("%d\n",ans);121     }122     return 0;123 }

 

 

原创粉丝点击