1834. [ZJOI2010]网络扩容【费用流】
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的答案。
Sample Input
5 8 2
1 2 5 8
2 5 9 9
5 1 6 2
5 1 1 8
1 2 8 7
2 5 4 9
1 2 1 1
1 4 2 1
1 2 5 8
2 5 9 9
5 1 6 2
5 1 1 8
1 2 8 7
2 5 4 9
1 2 1 1
1 4 2 1
Sample Output
13 19
这个思路非常的妙啊……被宽嫂一语点醒emmm
首先第一问求最大流是裸的问题瞎搞搞就行了……
不过我懒得再写一个Dinic就直接用的费用流跑的最大流
第二问我们将边拆掉
一条为容量为原本容量,费用为0
另一条容量为INF,费用为扩容费用(这意味着这个边可以无限扩容)
然后跑最小费用最大流就好了
那么k如何限定呢?
我们只需要再建立一个新汇点
在原汇点和新汇点间连接一条容量为MaxFlow+k的边,费用为0即可。
趁着宽嫂不注意
STO%%%Cansult%%%OTZ
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<queue> 6 #define MAXN (5000+10) 7 #define MAXM (50000+10) 8 using namespace std; 9 queue<int>q; 10 bool visit[MAXN]; 11 int pre[MAXN]; 12 int n,m,k,s,e,Ans,Fee; 13 int num_edge; 14 int head[MAXN]; 15 int dis[MAXN]; 16 bool used[MAXN]; 17 int INF; 18 struct node 19 { 20 int to; 21 int next; 22 int Flow;//残留网络 23 int Cost; 24 }edge[MAXM*2]; 25 26 void add(int u,int v,int l,int c) 27 { 28 edge[++num_edge].to=v; 29 edge[num_edge].next=head[u]; 30 edge[num_edge].Flow=l; 31 edge[num_edge].Cost=c; 32 head[u]=num_edge; 33 } 34 35 bool Spfa(int s,int e) 36 { 37 memset(pre,-1,sizeof(pre)); 38 memset(dis,0x7f,sizeof(dis)); 39 q.push(s); 40 dis[s]=0; 41 used[s]=true; 42 while (!q.empty()) 43 { 44 int x=q.front(); 45 q.pop(); 46 for (int i=head[x];i!=0;i=edge[i].next) 47 if (dis[x]+edge[i].Cost<dis[edge[i].to] && edge[i].Flow>0) 48 { 49 dis[edge[i].to]=edge[i].Cost+dis[x]; 50 pre[edge[i].to]=i; 51 if (!used[edge[i].to]) 52 { 53 used[edge[i].to]=true; 54 q.push(edge[i].to); 55 } 56 } 57 used[x]=false; 58 } 59 return (dis[e]!=INF); 60 } 61 62 void MCMF(int s,int e) 63 { 64 Ans=0,Fee=0; 65 while (Spfa(s,e)) 66 { 67 int d=INF; 68 for (int i=e;i!=s;i=edge[((pre[i]-1)^1)+1].to) 69 d=min(d,edge[pre[i]].Flow); 70 for (int i=e;i!=s;i=edge[((pre[i]-1)^1)+1].to) 71 { 72 edge[pre[i]].Flow-=d; 73 edge[((pre[i]-1)^1)+1].Flow+=d; 74 } 75 Ans+=d; 76 Fee+=d*dis[e]; 77 } 78 } 79 80 int main() 81 { 82 int u[MAXM],v[MAXM],l[MAXM],c[MAXM]; 83 memset(&INF,0x7f,sizeof(INF)); 84 scanf("%d%d%d",&n,&m,&k); 85 86 for (int i=1;i<=m;++i) 87 { 88 scanf("%d%d%d%d",&u[i],&v[i],&l[i],&c[i]); 89 add(u[i],v[i],l[i],0); 90 add(v[i],u[i],0,0); 91 } 92 MCMF(1,n); 93 printf("%d ",Ans);//MaxFlow 94 95 memset(head,0,sizeof(head)); 96 num_edge=0; 97 98 for (int i=1;i<=m;++i) 99 { 100 add(u[i],v[i],l[i],0); 101 add(v[i],u[i],0,0); 102 add(u[i],v[i],INF,c[i]); 103 add(v[i],u[i],0,-c[i]); 104 } 105 add(n,n+1,Ans+k,0); 106 add(n+1,n,0,0); 107 MCMF(1,n+1); 108 printf("%d",Fee); 109 }