hdu 3667 Transportation (拆边 ,最小费用流)

http://acm.hdu.edu.cn/showproblem.php?pid=3667

题意:

用 0 到 n-1 运送k 个货物,m条边,每条边,u,v,a,c,;  每条边表示 运送 x 单元货物的花费为  a * x*x,c 表示最大流量 ,

求 最小费用  ,若不能全部运送输出 -1;

 

题解:  拆边 ,看到这个题直接的思路就是费用流,一开始提了个模版 上去 发现不对,我们以前做的  花费是  a*f  ,而现在是  a*f*f(此时 以 最短路 已不能找到正确的答案);

所以我们要变为  a*f  ,那么就是,我们 发现 第一次运送时

费用为a,第二次取这条路时费用为3a(即流量为2时费用值为a+3a=4a),……,第i次取这条路时费用为(2*i-1)*a

在   u  到  u  连  c  条边,每条边的流量 为 1 ,费用   (2*i - 1)*a

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <queue>
  7 #include <stack>
  8 #include <set>
  9 #include <map>
 10 #include <string>
 11 
 12 #define CL(a,num) memset((a),(num),sizeof(a))
 13 #define iabs(x)  ((x) > 0 ? (x) : -(x))
 14 #define Min(a , b) ((a) < (b) ? (a) : (b))
 15 #define Max(a , b) ((a) > (b) ? (a) : (b))
 16 
 17 #define ll __int64
 18 #define inf 0x7f7f7f7f
 19 #define MOD 100000007
 20 #define lc l,m,rt<<1
 21 #define rc m + 1,r,rt<<1|1
 22 #define pi acos(-1.0)
 23 #define test puts("<------------------->")
 24 #define maxn 200
 25 #define M 507
 26 #define N 200
 27 using namespace std;
 28 //freopen("din.txt","r",stdin);
 29 
 30 
 31 struct node
 32 {
 33     int u,v;
 34     int c,w;
 35     int next;
 36 }g[maxn*1000];
 37 int head[maxn],cnt,pre[maxn];
 38 int dis[maxn];
 39 bool inq[maxn];
 40 int n,m,k,s,t,ans,res;
 41 
 42 
 43 void add(int u,int v,int c,int w){
 44     g[cnt].u = u; g[cnt].v = v; g[cnt].c = c; g[cnt].w = w;
 45     g[cnt].next = head[u]; head[u] = cnt++;
 46 
 47     g[cnt].u = v; g[cnt].v = u; g[cnt].c = 0; g[cnt].w = -w;
 48     g[cnt].next = head[v]; head[v] = cnt++;
 49 }
 50 void spfa(){
 51     int i;
 52 
 53     queue<int>q;
 54     for (i = 0; i <= t; ++i){
 55         dis[i] = inf;
 56         inq[i] = false;
 57         pre[i] = -1;
 58     }
 59     q.push(s); inq[s] = true;
 60     dis[s] = 0;
 61     while (!q.empty()){
 62         int u = q.front(); q.pop();
 63         inq[u] = false;
 64 
 65         for (i = head[u]; i != -1; i = g[i].next){
 66             int v = g[i].v;
 67             if (g[i].c && dis[v] > dis[u] + g[i].w){
 68                 dis[v] = dis[u] + g[i].w;
 69                 pre[v] = i;//注意这里记录的是这一条边了
 70                 if (!inq[v]){
 71                     inq[v] = true;
 72                     q.push(v);
 73                 }
 74             }
 75         }
 76     }
 77 }
 78 void mcmf(){
 79     ans = 0;
 80     res = 0 ;
 81 
 82    while (1){
 83        spfa();
 84        if (pre[t] == -1break;
 85        int x = t,minf = inf;
 86        while (x != s){
 87            minf = min(minf,g[pre[x]].c);
 88 
 89            x = g[pre[x]].u;
 90 
 91        }
 92        x = t;
 93        while (x != s){
 94            g[pre[x]].c -= minf;
 95            g[pre[x]^1].c += minf;
 96 
 97            x = g[pre[x]].u;
 98        }
 99         ans += minf*minf*dis[t];
100         res += minf;
101 
102    }
103     
104 }
105 
106 
107 void init()
108 {
109 
110     memset(head,-1,sizeof(head));
111     cnt = 0;
112 }
113 
114 int main()
115 {
116     int u,v,a,flow ,i,j;
117     while(scanf("%d%d%d",&n,&m,&k)!=EOF)
118     {
119         init() ;
120 
121         for(i = 0;i< m;i++)
122         {
123             scanf("%d%d%d%d",&u,&v,&a,&flow);
124 
125             
126             for(j = 0 ; j< flow;j++)
127                  add(u,v,1,a*(2*j + 1));
128 
129         }
130 
131         add(0,1,k,0) ;
132       
133         s = 0;
134         t = n ;
135         mcmf() ;
136         if(res < k)printf("-1\n");
137         else
138         {
139             printf("%d\n",ans) ;
140         }
141     }
142 }

 

 

posted @ 2012-10-14 20:59  Szz  阅读(294)  评论(0编辑  收藏  举报