传说中的凸费用流问题,对于一条有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 ",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 ",g.Maxflow); 99 } 100 return 0; 101 }