1. 程式人生 > >BZOJ 1834網絡擴容題解

BZOJ 1834網絡擴容題解

連接 真的 pty bzoj 什麽 擴容 大於 直接 dfs

一道不算太難的題目

但是真的很惡心

顯然,對於第一問,我們直接無腦打模板就好了

第二問也不是很難,我們將每條邊再連一條容量為inf,費用為w的邊

但是流量只要小於第一問的答案加k就行了

所以我們增加一個點為第二問的匯點,將n與它連接一條容量為ans+k,費用為0的邊

跑費用流就好了

但是!!!!!!!

這樣作只有40分,為什麽呢。

因為雖然數據範圍說n<=1000但給的點編號有大於1000的點。。。。。

我們只要將點數視為5000就可以過來了

真的惡心。。。。

不過在考場上還是建議用離散化,畢竟你不知道點數編號的範圍

想問一問當初省選時有多少人被這個給坑了。。

# include<iostream>
# include
<cstdio> # include<cmath> # include<algorithm> # include<cstring> # include<queue> using namespace std; const int mn = 5005; const int inf = 0xfffffff; struct edge{ int to,next,flow,cup,cost; edge(){to=flow=cup=cost=0,next=-1;} }; edge e[mn*10]; int head[mn],edge_max=-1; void
add(int x,int y,int k,double c) { e[++edge_max].to=y; e[edge_max].next=head[x]; e[edge_max].flow=e[edge_max].cup=k; e[edge_max].cost=c; head[x]=edge_max; } int n,m,k; int ans1,ans2; int deep[mn]; int cur[mn]; queue<int> q; bool bfs(int x,int y) { memset(deep,0,sizeof(deep)); q.push(x); deep[x]
=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=e[i].next) { if(deep[e[i].to]==0 && e[i].flow>0 ) { deep[e[i].to]=deep[u]+1; q.push(e[i].to); } } } if(deep[y]==0) return false; else return true; } int dfs(int x,int dist,int y) { if(x==y) return dist; for(int &i=cur[x];i!=-1;i=e[i].next) { if(deep[e[i].to]==deep[x]+1 && e[i].flow!=0) { int di=dfs(e[i].to,min(dist,e[i].flow),y); if(di>0) { e[i].flow-=di; e[i^1].flow+=di; return di; } } } return 0; } void dinic(int x,int y) { while(bfs(x,y)) { for(int i=1;i<=n;i++) cur[i]=head[i]; while(int k=dfs(x,inf,y)) ans1+=k; } } int dis[mn]; int pe[mn],pv[mn]; bool vis[mn]; bool spfa(int x,int y) { memset(vis,0,sizeof(vis)); for(int i=1;i<=n+1;i++) dis[i]=inf; dis[x]=0; vis[x]=1; q.push(x); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i!=-1;i=e[i].next) { if(dis[u]+e[i].cost<dis[e[i].to] && e[i].flow>0) { dis[e[i].to]=e[i].cost+dis[u]; pe[e[i].to]=i; pv[e[i].to]=u; if(!vis[e[i].to]) { q.push(e[i].to); vis[e[i].to]=1; } } } } if(dis[y]!=inf) return true; else return false; } void max_flow(int x,int y) { while(spfa(x,y)) { int mflow=inf; for(int i=y;i!=x;i=pv[i]) { mflow=min(mflow,e[pe[i]].flow); } ans2+=dis[y]*mflow; for(int i=y;i!=x;i=pv[i]) { e[pe[i]].flow-=mflow; e[pe[i]^1].flow+=mflow; } } } int a1[mn],a2[mn],a3[mn],a4[mn]; void pre() { memset(head,-1,sizeof(head)); memset(e,-1,sizeof(e)); for(int i=1;i<=m;i++) { add(a1[i],a2[i],a3[i],0); add(a2[i],a1[i],0,0); add(a1[i],a2[i],inf,a4[i]); add(a2[i],a1[i],0,-a4[i]); } } int main() { int x,y,c,w; memset(head,-1,sizeof(head)); scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&a1[i],&a2[i],&a3[i],&a4[i]); add(a1[i],a2[i],a3[i],0); add(a2[i],a1[i],0,0); } dinic(1,n); pre(); add(n,n+1,ans1+k,0); add(n+1,n,0,0); max_flow(1,n+1); printf("%d %d",ans1,ans2); return 0; }

BZOJ 1834網絡擴容題解