Bzoj:[ZJOI2010]network 网络扩容:网络流,最大流+费用流

来源:互联网 发布:儿童编程培训 价格 编辑:程序博客网 时间:2024/05/22 19:50

题目链接:1834:[ZJOI2010]network 网络扩容

好端端的一道水题让我给做的……

一开始我想的是先跑一边dinic得到残量网络,反正K不大然后就跑K遍费用流,每次跑费用流时碰到一条正向边没流满就把边权设为0,否则流量+1,边权为最开始的权值

但是这样傻X都能看出来是错的QAQ

加入跑了一遍费用流以后我们流量加过1的边并没有流到,那么他的权值就成0了,成0了,成0了……然后就GG了……

我还满心欢喜的写了半天,错了还以为是模板打错了QAQ

荏弱没话说……

这题我们一遍dinic后对于剩余图,只要这张图上的边是正边就复制一条容量为inf费用不变,反向边复制一条容量为0费用相反,并把原来的边的边权改为0

注意是复制原来的边保留,这样再次跑的时候由于原来的剩余边费用都为0会被优先选择

于是就对了……我还是太naive……

#include<queue>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=2000+10;const int inf=0x7fffffff/2-1;int n,m,h[maxn],tot=1,S,T,K,vis[maxn];struct edge{int to,next,w,c,f;}G[maxn*10];int dis[maxn],pre[maxn],cur[maxn];bool bfs(){for (int i=S;i<=T;++i) vis[i]=-1;queue<int>q; q.push(S); vis[S]=0;while (!q.empty()){int u=q.front(); q.pop();for (int i=h[u];i;i=G[i].next){int v=G[i].to;if (vis[v]==-1&&G[i].c>0){vis[v]=vis[u]+1; q.push(v);}}}return vis[T]!=-1;}int dfs(int x,int f){if (x==T||f==0) return f;int w,used=0;for (int i=cur[x];i;i=G[i].next)    if (G[i].c&&vis[x]+1==vis[G[i].to]){w=f-used;w=dfs(G[i].to,min(w,G[i].c));G[i].c-=w; G[i^1].c+=w;used+=w; if (used==f) return f;if (G[i].c) cur[x]=i;    }if (!used) vis[x]=-1;return used;}void dinic(){int ret=0;while (bfs()){for (int i=S;i<=T;++i) cur[i]=h[i];ret+=dfs(S,inf);}printf("%d ",ret);}void add(int x,int y,int c,int w){G[++tot].to=y; G[tot].next=h[x]; h[x]=tot;G[tot].c=c; G[tot].w=w; G[tot].f=x;}void rebuild(){int sum=tot; S=0; add(S,1,K,0); add(1,S,0,0);for (int i=2;i<=sum;++i)if (!(i&1)) add(G[i].f,G[i].to,inf,G[i].w),add(G[i].to,G[i].f,0,-G[i].w),G[i].w=G[i^1].w=0;}bool spfa(){for (int i=S;i<=T;++i){vis[i]=0;dis[i]=inf;pre[i]=-1;}vis[S]=1; dis[S]=0; deque<int>q; q.push_front(S);while (!q.empty()){int u=q.front(); q.pop_front(); vis[u]=0;for (int i=h[u];i;i=G[i].next){int v=G[i].to;if (dis[v]>dis[u]+G[i].w&&G[i].c>0){dis[v]=dis[u]+G[i].w;pre[v]=i; if (!vis[v]){ vis[v]=1;if (!q.empty()&&dis[v]<dis[q.front()])q.push_front(v);else q.push_back(v);}}}}return pre[T]!=-1;}void min_cost_flow(){int cost=0;while (spfa()){        int mf=inf; for (int i=pre[T];i!=-1;i=pre[G[i^1].to])    mf=min(mf,G[i].c);for (int i=pre[T];i!=-1;i=pre[G[i^1].to])    {G[i].c-=mf;G[i^1].c+=mf;cost+=G[i].w*mf;}}printf("%d",cost);}int main(){    scanf("%d%d%d",&n,&m,&K); S=1; T=n;for (int i=1;i<=m;++i){int a,b,c,d;scanf("%d%d%d%d",&a,&b,&c,&d);add(a,b,c,d); add(b,a,0,-d);}dinic(); rebuild(); min_cost_flow();}


2 1
原创粉丝点击