天天看點

HDU3667 Transportation —— 最小費用流(費用與流量平方成正比)Transportation

題目連結:https://vjudge.net/problem/HDU-3667

Transportation

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

Total Submission(s): 3083    Accepted Submission(s): 1341

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 a i. If you want to carry x units of goods along this road, you should pay a i * x 2 dollars to hire guards to protect your goods. And what’s worse, for each road i, there is an upper bound C i, which means that you cannot transport more than C i 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 (u i, v i, a i, C i), indicating there is a directed road from city u i to v i, whose coefficient is a i and upper bound is C i. (1 <= u i, v i <= N, 0 < a i <= 100, C i <= 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  

Source 2010 Asia Regional Harbin  

Recommend lcy

題解:

費用與流量平方成正比。詳情在《訓練指南》P366 。主要方法是拆邊。

代碼如下:

1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <vector>
  6 #include <cmath>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <string>
 11 #include <set>
 12 using namespace std;
 13 typedef long long LL;
 14 const int INF = 2e9;
 15 const LL LNF = 9e18;
 16 const int mod = 1e9+7;
 17 const int MAXM = 1e5+10;
 18 const int MAXN = 1e2+10;
 19 
 20 struct Edge
 21 {
 22     int to, next, cap, flow, cost;
 23 }edge[MAXM];
 24 int tot, head[MAXN];
 25 int pre[MAXN], dis[MAXN];
 26 bool vis[MAXN];
 27 int N;
 28 
 29 void init(int n)
 30 {
 31     N = n;
 32     tot = 0;
 33     memset(head, -1, sizeof(head));
 34 }
 35 
 36 void add(int u, int v, int cap, int cost)
 37 {
 38     edge[tot].to = v;  edge[tot].cap = cap;  edge[tot].cost = cost;
 39     edge[tot].flow = 0;   edge[tot].next = head[u];   head[u] = tot++;
 40     edge[tot].to = u;   edge[tot].cap = 0;  edge[tot].cost = -cost;
 41     edge[tot].flow = 0; edge[tot].next = head[v];   head[v] = tot++;
 42 }
 43 
 44 bool spfa(int s, int t)
 45 {
 46     queue<int>q;
 47     for(int i = 0; i<N; i++)
 48     {
 49         dis[i] = INF;
 50         vis[i] = false;
 51         pre[i] = -1;
 52     }
 53 
 54     dis[s] = 0;
 55     vis[s] = true;
 56     q.push(s);
 57     while(!q.empty())
 58     {
 59         int u  = q.front();
 60         q.pop();
 61         vis[u] = false;
 62         for(int i = head[u]; i!=-1; i = edge[i].next)
 63         {
 64             int v = edge[i].to;
 65             if(edge[i].cap>edge[i].flow && dis[v]>dis[u]+edge[i].cost)
 66             {
 67                 dis[v] = dis[u]+edge[i].cost;
 68                 pre[v] = i;
 69                 if(!vis[v])
 70                 {
 71                     vis[v] = true;
 72                     q.push(v);
 73                 }
 74             }
 75         }
 76     }
 77     if(pre[t]==-1) return false;
 78     return true;
 79 }
 80 
 81 int minCostMaxFlow(int s, int t, int &cost)
 82 {
 83     int flow = 0;
 84     cost = 0;
 85     while(spfa(s,t))
 86     {
 87         int Min = INF;
 88         for(int i = pre[t]; i!=-1; i = pre[edge[i^1].to])
 89         {
 90             if(Min>edge[i].cap-edge[i].flow)
 91                 Min = edge[i].cap-edge[i].flow;
 92         }
 93         for(int i = pre[t]; i!=-1; i = pre[edge[i^1].to])
 94         {
 95             edge[i].flow += Min;
 96             edge[i^1].flow -= Min;
 97             cost += edge[i].cost*Min;
 98         }
 99         flow += Min;
100     }
101     return flow;
102 }
103 
104 int main()
105 {
106     int n, m, K;
107     while(scanf("%d%d%d", &n, &m, &K)!=EOF)
108     {
109         init(n+1);
110         for(int i = 1; i<=m; i++)
111         {
112             int u, v, c, a;
113             scanf("%d%d%d%d", &u, &v, &a, &c);
114             for(int j = 1; j<=c; j++)   //拆邊
115                 add(u, v, 1, (j*2-1)*a);    //拆成費用為1 3 5 7 9……的邊,每條邊的容量為1
116         }
117         add(0, 1, K, 0);
118 
119         int min_cost;
120         int start = 0, end = n;
121         int max_flow = minCostMaxFlow(start, end, min_cost);
122 
123         if(max_flow<K) printf("-1\n");
124         else printf("%d\n", min_cost);
125     }
126 }      

View Code

轉載于:https://www.cnblogs.com/DOLFAMINGO/p/8117243.html