zoukankan      html  css  js  c++  java
  • HDU3667 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 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
     
    Source
     
    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
    ");
    124         else printf("%d
    ", min_cost);
    125     }
    126 }
    View Code
  • 相关阅读:
    201671010127 2016—2017-2 通过一个小程序对Java的再认识。
    201671010127 2016—2017—2 面向对象的基本概念
    201671010127 2016—2017-2 java编程中遇到的问题
    201671010127 2016—2017—2 Java怎样解决Java程序中中文乱码的问题。
    201671010127 2016—2017—2 Java学习周结
    201671010127 2016—2017-2 java学习新征程
    Linux下C语言编程实现spwd函数
    20145221 《信息安全系统设计基础》第10周学习总结
    20145221 《信息安全系统设计基础》实验三 实时系统的移植
    Linux下who命令之C语言实现
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8117243.html
Copyright © 2011-2022 走看看