题目描述
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。
求:
1、在不扩容的情况下,1到N的最大流;
2、将1到N的最大流增加K所需的最小扩容费用。
输入
第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。
接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
N<=1000,M<=5000,K<=10
输出
输出文件一行包含两个整数,分别表示问题1和问题2的答案。
第一问没啥可说的,直接最大流就行。第二问显然是求最小费用最大流,第二次加边直接残量网络上把对应边建出来,不用再重新建图,只要把第一次建的边边权赋成INF,就能保证一定走的是第二次加的边。第二次加的边因为不确定每条边容量,所以都设成INF,但又要限制总流量,所以新建一个源点连一条边到原来的源点,容量为k,这样就保证了全图流量。
最后附上代码。
1 #include<cmath> 2 #include<queue> 3 #include<cstdio> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 using namespace std; 8 queue<int>Q; 9 int A[5010]; 10 int B[5010]; 11 int C[5010]; 12 int D[5010]; 13 int f[5010]; 14 int vis[5010]; 15 int c[100001]; 16 int d[100001]; 17 int q[100001]; 18 int to[100001]; 19 int val[100001]; 20 int next[100001]; 21 int from[100001]; 22 int head[100001]; 23 int S,T; 24 int sum; 25 int ans=0; 26 int tot=1; 27 int n,m,k; 28 int max_flow=0; 29 int INF=2147483647; 30 void add(int x,int y,int z,int w) 31 { 32 tot++; 33 next[tot]=head[x]; 34 head[x]=tot; 35 to[tot]=y; 36 c[tot]=z; 37 val[tot]=w; 38 from[tot]=x; 39 tot++; 40 next[tot]=head[y]; 41 head[y]=tot; 42 to[tot]=x; 43 c[tot]=0; 44 val[tot]=-w; 45 from[tot]=y; 46 } 47 int dfs(int x,int maxflow) 48 { 49 if(x==T) 50 { 51 return maxflow; 52 } 53 int used=0; 54 int nowflow; 55 for(int i=head[x];i;i=next[i]) 56 { 57 if(c[i]!=0&&d[to[i]]==d[x]+1) 58 { 59 nowflow=dfs(to[i],min(maxflow-used,c[i])); 60 c[i]-=nowflow; 61 c[i^1]+=nowflow; 62 used+=nowflow; 63 if(nowflow==maxflow) 64 { 65 return maxflow; 66 } 67 } 68 } 69 if(used==0) 70 { 71 d[x]=-1; 72 } 73 return used; 74 } 75 bool bfs(int S,int T) 76 { 77 memset(d,-1,sizeof(d)); 78 memset(q,0,sizeof(q)); 79 d[S]=0; 80 int l=0; 81 int r=0; 82 q[r++]=S; 83 while(l<r) 84 { 85 int now=q[l]; 86 for(int i=head[now];i;i=next[i]) 87 { 88 if(d[to[i]]==-1&&c[i]!=0) 89 { 90 d[to[i]]=d[now]+1; 91 q[r++]=to[i]; 92 } 93 } 94 l++; 95 } 96 if(d[T]!=-1) 97 { 98 return true; 99 } 100 return false; 101 } 102 void dinic() 103 { 104 while(bfs(S,T)==true) 105 { 106 ans+=dfs(S,INF); 107 } 108 } 109 bool SPFA() 110 { 111 for(int i=0;i<=T;i++) 112 { 113 d[i]=INF; 114 } 115 d[S]=0; 116 Q.push(S); 117 vis[S]=1; 118 while(!Q.empty()) 119 { 120 int now=Q.front(); 121 Q.pop(); 122 vis[now]=0; 123 for(int i=head[now];i;i=next[i]) 124 { 125 if(!c[i]) 126 { 127 continue; 128 } 129 if(d[to[i]]>d[now]+val[i]) 130 { 131 d[to[i]]=d[now]+val[i]; 132 f[to[i]]=i; 133 if(!vis[to[i]]) 134 { 135 Q.push(to[i]); 136 vis[to[i]]=1; 137 } 138 } 139 } 140 } 141 return d[T]!=INF; 142 } 143 void result() 144 { 145 int now=T; 146 int flow=INF; 147 while(now!=S) 148 { 149 flow=min(flow,c[f[now]]); 150 now=from[f[now]]; 151 } 152 max_flow+=flow; 153 sum+=d[T]*flow; 154 now=T; 155 while(now!=S) 156 { 157 c[f[now]]-=flow; 158 c[f[now]^1]+=flow; 159 now=from[f[now]]; 160 } 161 } 162 void find_min() 163 { 164 while(SPFA()) 165 { 166 result(); 167 } 168 } 169 int main() 170 { 171 scanf("%d%d%d",&n,&m,&k); 172 S=1; 173 T=n; 174 for(int i=1;i<=m;i++) 175 { 176 scanf("%d%d%d%d",&A[i],&B[i],&C[i],&D[i]); 177 add(A[i],B[i],C[i],0); 178 } 179 dinic(); 180 printf("%d ",ans); 181 for(int i=1;i<=m;i++) 182 { 183 add(A[i],B[i],INF,D[i]); 184 } 185 S=0; 186 add(S,1,k,0); 187 find_min(); 188 printf("%d",sum); 189 }