【BZOJ】1834 [ZJOI2010]network 网络扩容
【算法】网络流-最大流+最小费用最大流(费用流)
【题解】
第一问跑最大流。
第二问:
原始边相当于费用为0的边,再原图(跑过最大流的图)基础上添加带费用的边,容量为k(相当于inf)。
第一问最大流使用了哪条边对第二问没有影响,因为费用流肯定优先往费用为0的边(原始边)跑。
限流k?添加超级源向1连容量k费用0的边即可。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1010,maxm=10010,N=1005,inf=0x3f3f3f3f; int tot=1,first[maxn],d[maxn],q[maxn],cur[maxn],S,T,sum,n,m,K,u[maxm],v[maxm],w[maxm]; bool vis[maxn]; struct edge{int v,f,c,from;}e[maxm*2]; void insert(int u,int v,int f,int c){ tot++;e[tot].v=v;e[tot].f=f;e[tot].c=c;e[tot].from=first[u];first[u]=tot; tot++;e[tot].v=u;e[tot].f=0;e[tot].c=-c;e[tot].from=first[v];first[v]=tot; } bool bfs(){ memset(d,-1,sizeof(d)); int head=0,tail=1;q[head]=S;d[S]=0; while(head<tail){ int x=q[head++]; for(int i=first[x];i;i=e[i].from) if(e[i].f&&d[e[i].v]==-1){ d[e[i].v]=d[x]+1; q[tail++]=e[i].v; } } return ~d[T]; } int dinic(int x,int a){ if(x==T||a==0)return a; int flow=0,f; for(int& i=cur[x];i;i=e[i].from) if(d[e[i].v]==d[x]+1&&(f=dinic(e[i].v,min(e[i].f,a)))){ e[i].f-=f;e[i^1].f+=f; flow+=f;a-=f; if(a==0)break; } return flow; } int solve1(){ int ans=0; while(bfs()){ for(int i=S;i<=T;i++)cur[i]=first[i]; ans+=dinic(S,inf); } return ans; } bool spfa(){ memset(d,0x3f,sizeof(d)); int head=0,tail=1;q[head]=T;d[T]=0;vis[T]=1; while(head!=tail){ int x=q[head++];if(head>N)head=0; for(int i=first[x];i;i=e[i].from) if(e[i^1].f&&d[x]+e[i^1].c<d[e[i].v]){ d[e[i].v]=d[x]+e[i^1].c; if(!vis[e[i].v]){ if(d[e[i].v]<d[q[head]]){if(--head<0)head=N;q[head]=e[i].v;} else{q[tail++]=e[i].v;if(tail>N)tail=0;} vis[e[i].v]=1; } } vis[x]=0;// } return d[S]<inf; } int dfs(int x,int a){ if(x==T||a==0)return a; vis[x]=1; int flow=0,f; for(int& i=cur[x];i;i=e[i].from) if(!vis[e[i].v]&&d[e[i].v]+e[i].c==d[x]&&(f=dfs(e[i].v,min(e[i].f,a)))){ e[i].f-=f;e[i^1].f+=f; sum+=e[i].c*f; flow+=f;a-=f; if(a==0)break; } vis[x]=0; return flow; } int solve2(){ sum=0; while(spfa()){ for(int i=S;i<=T;i++)cur[i]=first[i]; dfs(S,inf); } return sum; } int main(){ scanf("%d%d%d",&n,&m,&K); S=1;T=n; for(int i=1;i<=m;i++){ int c; scanf("%d%d%d%d",&u[i],&v[i],&c,&w[i]); insert(u[i],v[i],c,0); } printf("%d ",solve1()); S=0; for(int i=1;i<=m;i++)insert(u[i],v[i],K,w[i]); insert(S,1,K,0); printf("%d",solve2()); return 0; }
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1010,maxm=10010,N=1005,inf=0x3f3f3f3f; int tot=1,first[maxn],d[maxn],q[maxn],cur[maxn],S,T,sum,n,m,K,u[maxm],v[maxm],w[maxm],c[maxm]; bool vis[maxn]; struct edge{int v,f,c,from;}e[maxm*2]; void insert(int u,int v,int f,int c){ tot++;e[tot].v=v;e[tot].f=f;e[tot].c=c;e[tot].from=first[u];first[u]=tot; tot++;e[tot].v=u;e[tot].f=0;e[tot].c=-c;e[tot].from=first[v];first[v]=tot; } bool bfs(){ memset(d,-1,sizeof(d)); int head=0,tail=1;q[head]=S;d[S]=0; while(head<tail){ int x=q[head++]; for(int i=first[x];i;i=e[i].from) if(e[i].f&&d[e[i].v]==-1){ d[e[i].v]=d[x]+1; q[tail++]=e[i].v; } } return ~d[T]; } int dinic(int x,int a){ if(x==T||a==0)return a; int flow=0,f; for(int& i=cur[x];i;i=e[i].from) if(d[e[i].v]==d[x]+1&&(f=dinic(e[i].v,min(e[i].f,a)))){ e[i].f-=f;e[i^1].f+=f; flow+=f;a-=f; if(a==0)break; } return flow; } int solve1(){ int ans=0; while(bfs()){ for(int i=S;i<=T;i++)cur[i]=first[i]; ans+=dinic(S,inf); } return ans; } bool spfa(){ memset(d,0x3f,sizeof(d)); int head=0,tail=1;q[head]=T;d[T]=0;vis[T]=1; while(head!=tail){ int x=q[head++];if(head>N)head=0; for(int i=first[x];i;i=e[i].from) if(e[i^1].f&&d[x]+e[i^1].c<d[e[i].v]){ d[e[i].v]=d[x]+e[i^1].c; if(!vis[e[i].v]){ if(d[e[i].v]<d[q[head]]){if(--head<0)head=N;q[head]=e[i].v;} else{q[tail++]=e[i].v;if(tail>N)tail=0;} vis[e[i].v]=1; } } vis[x]=0;// } return d[S]<inf; } int dfs(int x,int a){ if(x==T||a==0)return a; vis[x]=1; int flow=0,f; for(int& i=cur[x];i;i=e[i].from) if(!vis[e[i].v]&&d[e[i].v]+e[i].c==d[x]&&(f=dfs(e[i].v,min(e[i].f,a)))){ e[i].f-=f;e[i^1].f+=f; sum+=e[i].c*f; flow+=f;a-=f; if(a==0)break; } vis[x]=0; return flow; } int solve2(){ sum=0; while(spfa()){ for(int i=S;i<=T;i++)cur[i]=first[i]; dfs(S,inf); } return sum; } int main(){ scanf("%d%d%d",&n,&m,&K); S=1;T=n; for(int i=1;i<=m;i++){ scanf("%d%d%d%d",&u[i],&v[i],&c[i],&w[i]); insert(u[i],v[i],c[i],0); } int now=0; printf("%d ",now=solve1()); tot=1;memset(first,0,sizeof(first));// for(int i=1;i<=m;i++){ insert(u[i],v[i],c[i],0); insert(u[i],v[i],K,w[i]); } S=0; insert(S,1,now+K,0); printf("%d",solve2()); return 0; }