【费用流】bzoj1834: [ZJOI2010]network 网络扩容

还是稍微记一下这个拆点模型吧

Description

给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。
求: 
1、在不扩容的情况下,1到N的最大流; 
2、将1到N的最大流增加K所需的最小扩容费用。

Input

第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 
接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
N<=1000,M<=5000,K<=10

Output

输出文件一行包含两个整数,分别表示问题1和问题2的答案。


 

题目分析

这里只考虑第二问:第一眼看上去像是二分或者最小费用可行流。然而在残量网络里将源点拆为$S$和$S‘$再连$(S,S',K,0)$的边来限制图中新增的费用是一种更好的模型。

以后再遇到个数限制时候,要及时想到 拆点 的这一类处理方式。

 1 #include<bits/stdc++.h>
 2 //const int maxn = 1035;
 3 const int maxm = 20035;
 4 const int maxNode = 1035;
 5 const int INF = 2e9;
 6 
 7 struct Edge
 8 {
 9     int u,v,f,c,cst;
10     Edge(int a=0, int b=0, int c=0, int d=0, int e=0):u(a),v(b),f(c),c(d),cst(e) {}
11 }edges[maxm],sv[maxm];
12 int n,m,K,ans1,ans2,S,T,SS;
13 int edgeTot,head[maxNode],nxt[maxm],bck[maxNode],cst[maxNode],flw[maxNode];
14 bool inq[maxNode];
15 
16 int read()
17 {
18     char ch = getchar();
19     int num = 0, fl = 1;
20     for (; !isdigit(ch); ch=getchar())
21         if (ch=='-') fl = -1;
22     for (; isdigit(ch); ch=getchar())
23         num = (num<<1)+(num<<3)+ch-48;
24     return num*fl;
25 }
26 void addedge(int u, int v, int c, int cst)
27 {
28     edges[edgeTot] = Edge(u, v, 0, c,  cst), nxt[edgeTot] = head[u], head[u] = edgeTot, ++edgeTot;
29     edges[edgeTot] = Edge(v, u, 0, 0, -cst), nxt[edgeTot] = head[v], head[v] = edgeTot, ++edgeTot;
30 }
31 std::pair<int, int> maxFlow()
32 {
33     int flow = 0, cost = 0;
34     for (;;)
35     {
36         std::queue<int> q;
37         memset(bck, 0, sizeof bck);
38         memset(flw, 0, sizeof flw);
39         memset(cst, 0x3f3f3f3f, sizeof cst);
40         q.push(S), cst[S] = 0, flw[S] = INF;
41         for (int tmp; q.size(); )
42         {
43             tmp = q.front(), q.pop(), inq[tmp] = 0;
44             for (int i=head[tmp]; i!=-1; i=nxt[i])
45             {
46                 int v = edges[i].v;
47                 if (cst[v] > cst[tmp]+edges[i].cst&&edges[i].f < edges[i].c){
48                     cst[v] = cst[tmp]+edges[i].cst, bck[v] = i;
49                     flw[v] = std::min(flw[tmp], edges[i].c-edges[i].f);
50                     if (!inq[v]) q.push(v), inq[v] = 1;
51                 }
52             }
53         }
54         if (!flw[T]) break;
55         for (int i=T; i!=S; i=edges[bck[i]].u)
56             edges[bck[i]].f += flw[T], edges[bck[i]^1].f -= flw[T];
57         flow += flw[T], cost += flw[T]*cst[T];
58     }
59     return std::make_pair(flow, cost);
60 }
61 int main()
62 {
63     memset(head, -1, sizeof head);
64     n = read(), m = read(), K = read();
65     for (int i=1; i<=m; i++)
66     {
67         int u = read(), v = read(), c = read(), cst = read();
68         sv[i] = Edge(u, v, 0, c, cst), addedge(u, v, c, 0);
69     }
70     SS = 0, S = 1, T = n;
71     ans1 = maxFlow().first;
72     std::swap(S, SS);
73     addedge(S, SS, K, 0);
74     for (int i=1; i<=m; i++)
75         addedge(sv[i].u, sv[i].v, INF, sv[i].cst);
76     ans2 = maxFlow().second;
77     printf("%d %d\n",ans1,ans2);
78     return 0;
79 }

 

 

END

posted @ 2019-03-06 21:20  AntiQuality  阅读(204)  评论(0编辑  收藏  举报