|
网络流/费用流这题……我一开始sb了。
第一问简单的最大流……
第二问是要建费用流的图的……但是是在第一问的最大流跑完以后的残量网络上建,而不是重建……
我们令残量网络上原有的弧的费用全部为0(因为如果还能走就不需要扩容),而新加的弧容量为INF,费用为给定的w。
然后跑费用流就好了……这样建的话如果是不用扩容的边它就会自己走费用为0的弧。
RE/TLE:费用流扩展时的队列/边集数组的大小 M 开小了,队列长度从N改成M,M大小从20000改成50000后AC
1 /**************************************************************
2 Problem: 1834
3 User: Tunix
4 Language: C++
5 Result: Accepted
6 Time:36 ms
7 Memory:3824 kb
8 ****************************************************************/
9
10 //BZOJ 1834
11 #include<vector>
12 #include<cstdio>
13 #include<cstring>
14 #include<cstdlib>
15 #include<iostream>
16 #include<algorithm>
17 #define rep(i,n) for(int i=0;i<n;++i)
18 #define F(i,j,n) for(int i=j;i<=n;++i)
19 #define D(i,j,n) for(int i=j;i>=n;--i)
20 #define pb push_back
21 using namespace std;
22 inline int getint(){
23 int v=0,sign=1; char ch=getchar();
24 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
25 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
26 return v*sign;
27 }
28 const int N=1002,M=50000,INF=~0u>>2;
29 typedef long long LL;
30 /******************tamplate*********************/
31 int n,m,k,ans;
32 struct edge{int from,to,v,c,w;};
33 struct Net{
34 edge E[M],G[M];
35 int head[N],next[M],cnt;
36 void ins(int x,int y,int v,int c){
37 E[++cnt]=(edge){x,y,v,0,c};
38 next[cnt]=head[x]; head[x]=cnt;
39 }
40 void add(int x,int y,int v,int c){
41 ins(x,y,v,c); ins(y,x,0,-c);
42 }
43 void Ins(int x,int y,int v,int c){
44 E[++cnt]=(edge){x,y,v,c,0};
45 next[cnt]=head[x]; head[x]=cnt;
46 }
47 void Add(int x,int y,int v,int c){
48 Ins(x,y,v,c); Ins(y,x,0,-c);
49 }
50 int s,t,d[N],Q[M];
51 bool mklevel(){
52 F(i,1,n) d[i]=-1;
53 d[s]=0;
54 int l=0,r=-1;
55 Q[++r]=s;
56 while(l<=r){
57 int x=Q[l++];
58 for(int i=head[x];i;i=next[i])
59 if (d[E[i].to]==-1 && E[i].v){
60 d[E[i].to]=d[x]+1;
61 Q[++r]=E[i].to;
62 }
63 }
64 return d[t]!=-1;
65 }
66 int dfs(int x,int a){
67 if (x==t) return a;
68 int flow=0;
69 for(int i=head[x];i && flow<a;i=next[i])
70 if (E[i].v && d[E[i].to]==d[x]+1){
71 int f=dfs(E[i].to,min(a-flow,E[i].v));
72 E[i].v-=f;
73 E[i^1].v+=f;
74 flow+=f;
75 }
76 if (!flow) d[x]=-1;
77 return flow;
78 }
79 void Dinic(){
80 while(mklevel()) ans+=dfs(s,INF);
81 }
82 int from[M];
83 bool inq[N];
84 bool spfa(){
85 int l=0,r=-1;
86 F(i,0,n) d[i]=INF;
87 d[s]=0; Q[++r]=s; inq[s]=1;
88 while(l<=r){
89 int x=Q[l++];
90 inq[x]=0;
91 for(int i=head[x];i;i=next[i])
92 if (E[i].v>0 && d[x]+E[i].c<d[E[i].to]){
93 d[E[i].to]=d[x]+E[i].c;
94 from[E[i].to]=i;
95 if (!inq[E[i].to]){
96 Q[++r]=E[i].to;
97 inq[E[i].to]=1;
98 }
99 }
100 }
101 return d[n]!=INF;
102 }
103 void mcf(){
104 int x=INF;
105 for(int i=from[t];i;i=from[E[i].from])
106 x=min(x,E[i].v);
107 for(int i=from[t];i;i=from[E[i].from]){
108 E[i].v-=x;
109 E[i^1].v+=x;
110 ans+=x*E[i].c;
111 }
112 }
113 void build(){
114 int t=cnt;
115 for(int i=2;i<=t;i+=2)
116 Add(E[i].from,E[i].to,INF,E[i].w);
117 }
118 void init(){
119 n=getint(); m=getint(); k=getint();
120 int x,y,z,w;
121 cnt=1;
122 s=1; t=n;
123 F(i,1,m){
124 x=getint(); y=getint(); z=getint(); w=getint();
125 add(x,y,z,w);
126 }
127 Dinic(); build();
128 printf("%d ",ans);
129 ans=0; s=0;
130 ins(s,1,k,0);
131 while(spfa()) mcf();
132 printf("%d\n",ans);
133 }
134 }G1;
135
136 int main(){
137 #ifndef ONLINE_JUDGE
138 freopen("1834.in","r",stdin);
139 freopen("1834.out","w",stdout);
140 #endif
141 G1.init();
142 return 0;
143 } View Code
1834: [ZJOI2010]network 网络扩容
Time Limit: 3 Sec Memory Limit: 64 MB
Submit: 1976 Solved: 986
[Submit][Status][Discuss]
Description
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。
Input
输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
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
Sample Output
13 19
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
HINT
Source
Day1
[Submit][Status][Discuss]
|
免责声明:
1. 本站所有资源来自网络搜集或用户上传,仅作为参考不担保其准确性!
2. 本站内容仅供学习和交流使用,版权归原作者所有!© 查看更多
3. 如有内容侵害到您,请联系我们尽快删除,邮箱:kf@codeae.com
|