1. 程式人生 > >bzoj 1834: [ZJOI2010]network 網絡擴容【最大流+最小費用最大流】

bzoj 1834: [ZJOI2010]network 網絡擴容【最大流+最小費用最大流】

mark 建圖 network 最小 bfs source include tdi down

第一問直接跑最大流即可。建圖的時候按照費用流建,費用為0.
對於第二問,在第一問dinic剩下的殘量網絡上建圖,對原圖的每條邊(i,j),建(i,j,inf,cij),表示可以用c的花費增廣這條路。然後從新建一個源點,連(s,1,k,0)表示要增加k的流量。跑最小費用最大流即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=1000005,inf=1e9;
int n,m,k,h[N],cnt=1,le[N],s,t,ans,dis[N],fr[N],c[N];
bool
v[N]; struct qwe { int ne,no,to,va,c; }e[N]; int read() { int r=0,f=1; char p=getchar(); while(p>‘9‘||p<‘0‘) { if(p==‘-‘) f=-1; p=getchar(); } while(p>=‘0‘&&p<=‘9‘) { r=r*10+p-48; p=getchar(); } return
r*f; } void add(int u,int v,int w,int c) { cnt++; e[cnt].ne=h[u]; e[cnt].no=u; e[cnt].to=v; e[cnt].va=w; e[cnt].c=c; h[u]=cnt; } void ins(int u,int v,int w,int c) { add(u,v,w,c); add(v,u,0,-c); } bool bfs() { queue<int>q; memset(le,0,sizeof(le)); le[s]=1
; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=h[u];i;i=e[i].ne) if(e[i].va>0&&!le[e[i].to]) { le[e[i].to]=le[u]+1; q.push(e[i].to); } } return le[t]; } int dfs(int u,int f) { if(!f||u==t) return f; int us=0; for(int i=h[u];i&&us<f;i=e[i].ne) if(e[i].va>0&&le[e[i].to]==le[u]+1) { int t=dfs(e[i].to,min(e[i].va,f-us)); e[i].va-=t; e[i^1].va+=t; us+=t; } if(!us) le[u]=0; return us; } int dinic() { int re=0; while(bfs()) re+=dfs(s,inf); return re; } bool spfa() { queue<int>q; for(int i=s;i<=t;i++) dis[i]=inf; dis[s]=0; v[s]=0; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); v[u]=0; for(int i=h[u];i;i=e[i].ne) if(e[i].va>0&&dis[e[i].to]>dis[u]+e[i].c) { dis[e[i].to]=dis[u]+e[i].c; fr[e[i].to]=i; if(!v[e[i].to]) { v[e[i].to]=1; q.push(e[i].to); } } } return dis[t]!=inf; } void mcf() { int x=inf; for(int i=fr[t];i;i=fr[e[i].no]) x=min(x,e[i].va); for(int i=fr[t];i;i=fr[e[i].no]) { e[i].va-=x; e[i^1].va+=x; ans+=e[i].c*x; } } int main() { n=read(),m=read(),k=read(); s=1,t=n; for(int i=1;i<=m;i++) { int x=read(),y=read(),z=read();c[i]=read(); ins(x,y,z,0); } printf("%d ",dinic()); s=0,t=n; int now=cnt; for(int i=2;i<=now;i+=2) ins(e[i].no,e[i].to,inf,c[i>>1]); ins(s,1,k,0); while(spfa()) mcf(); printf("%d\n",ans); return 0; }

bzoj 1834: [ZJOI2010]network 網絡擴容【最大流+最小費用最大流】