HOJ 2543 Stone IV

传说中的凸费用流问题,对于一条有c1容量免费,超出容量部分增加的每单位流量费用为c2的边(u,v),在原图中拆成两条边(u,v,c1,0),(u,v,INF,c2)。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <queue>
  6 #define maxn 1010
  7 #define maxm 200010
  8 #define INF 0x3f3f3f3f
  9 using namespace std;
 10 typedef long long LL;
 11 int N,M,C,P;
 12 struct MCMF{
 13     int src,sink,e,n;
 14     int first[maxn];
 15     int cap[maxm],cost[maxm],v[maxm],next[maxm];
 16     bool flag;
 17     void init(){
 18         e = 0;
 19         memset(first,-1,sizeof(first));
 20     }
 21 
 22     void add_edge(int a,int b,int cc,int ww){
 23         //printf("add:%d to %d,cap = %d,cost = %d\n",a,b,cc,ww);
 24         cap[e] = cc;cost[e] = ww;v[e] = b;
 25         next[e] = first[a];first[a] = e++;
 26         cap[e] = 0;cost[e] = -ww;v[e] = a;
 27         next[e] = first[b];first[b] = e++;
 28     }
 29 
 30     int d[maxn],pre[maxn],pos[maxn];
 31     bool vis[maxn];
 32 
 33     bool spfa(int s,int t){
 34         memset(pre,-1,sizeof(pre));
 35         memset(vis,0,sizeof(vis));
 36         queue<int> Q;
 37         for(int i = 0;i <= n;i++)   d[i] = INF;
 38         Q.push(s);pre[s] = s;d[s] = 0;vis[s] = 1;
 39         while(!Q.empty()){
 40             int u = Q.front();Q.pop();
 41             vis[u] = 0;
 42             for(int i = first[u];i != -1;i = next[i]){
 43                 if(cap[i] > 0 && d[u] + cost[i] < d[v[i]]){
 44                     d[v[i]] = d[u] + cost[i];
 45                     pre[v[i]] = u;pos[v[i]] = i;
 46                     if(!vis[v[i]])  vis[v[i]] = 1,Q.push(v[i]);
 47                 }
 48             }
 49         }
 50         return pre[t] != -1;
 51     }
 52 
 53     LL Mincost;
 54     int Maxflow;
 55 
 56     int MinCostFlow(int s,int t,int nn){
 57         Mincost = 0,Maxflow = 0,n = nn;
 58         while(spfa(s,t)){
 59             LL min_f = INF;
 60             for(int i = t;i != s;i = pre[i])
 61                 if(cap[pos[i]] < min_f) min_f = cap[pos[i]];
 62             Mincost += d[t] * min_f;
 63             Maxflow += min_f;
 64             if(Mincost > C){
 65                 Maxflow -= ceil((Mincost - C) * 1.0 / d[t]);
 66                 break;
 67             }
 68             for(int i = t;i != s;i = pre[i]){
 69                 cap[pos[i]] -= min_f;
 70                 cap[pos[i]^1] += min_f;
 71             }
 72         }
 73         return Mincost;
 74     }
 75 };
 76 
 77 
 78 MCMF g;
 79 
 80 int main(){
 81     int T;
 82     scanf("%d",&T);
 83     while(T--){
 84         scanf("%d%d%d%d",&N,&M,&C,&P);
 85         g.init();
 86         int src = N+1,sink = 2;
 87         g.add_edge(src,1,INF,P);
 88         for(int i = 1;i <= M;i++){
 89             int u,v,c1,c2;
 90             scanf("%d%d%d%d",&u,&v,&c1,&c2);
 91             u++;v++;
 92             g.add_edge(u,v,c1,0);
 93             g.add_edge(v,u,c1,0);
 94             g.add_edge(u,v,INF,c2);
 95             g.add_edge(v,u,INF,c2);
 96         }
 97         g.MinCostFlow(src,sink,src);
 98         printf("%d\n",g.Maxflow);
 99     }
100     return 0;
101 }
View Code

 

posted @ 2013-10-06 13:34  浙西贫农  阅读(202)  评论(0编辑  收藏  举报