有上下界最大流初步zoj2314

来源:互联网 发布:ido视频软件 编辑:程序博客网 时间:2024/05/09 02:40

题意:

   给n个点,及m根pipe,每根pipe用来流躺液体的,单向的,每时每刻每根pipe流进来的物质要等于流出去的物质,要使得m条pipe组成一个循环体,里面流躺物质。

并且满足每根pipe一定的流量限制,范围为[Li,Ri].即要满足每时刻流进来的不能超过Ri(最大流问题),同时最小不能低于Li。

题解:

上界用ci表示,下界用bi表示。

下界是必须流满的,那么对于每一条边,去掉下界后,其自由流为ci– bi。

主要思想:每一个点流进来的流=流出去的流

对于每一个点i,令

Mi= sum(i点所有流进来的下界流)– sum(i点所有流出去的下界流)

如果Mi大于0,代表此点必须还要流出去Mi的自由流,那么我们从源点连一条Mi的边到该点。

如果Mi小于0,代表此点必须还要流进来Mi的自由流,那么我们从该点连一条Mi的边到汇点。

如果求S->T的最大流,看是否满流(S的相邻边都流满)。

满流则有解,否则无解。


上下界问题中的实际流量就是:建图后流量+原先下界流量

模板

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<queue>#include<algorithm>using namespace std;const int inf=0x3f3f3f3f;inline int read(){int ans,f=1;char ch;while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';return ans*f;}int n,m,tot,cur[205],head[205],T,S,in[205];int low[100005];struct aa{int to,pre,flow,cap;}edge[100005];void addedge(int u,int v,int d){edge[++tot].to=v;edge[tot].pre=head[u];edge[tot].cap=d;edge[tot].flow=0;head[u]=tot;edge[++tot].to=u;edge[tot].pre=head[v];edge[tot].cap=0;edge[tot].flow=0;head[v]=tot;}void build(){for (int i=1;i<=n;i++) if (in[i]>0) addedge(S,i,in[i]);else addedge(i,T,-in[i]);}int lev[205];bool bfs(){memset(lev,0,sizeof(lev));lev[S]=1;queue<int> q;q.push(S);while (!q.empty()){int u=q.front();q.pop();for (int i=head[u];i;i=edge[i].pre)if (edge[i].cap>edge[i].flow&&lev[edge[i].to]==0){lev[edge[i].to]=lev[u]+1;if (edge[i].to==T) return true;q.push(edge[i].to);}}return false;}int dfs(int u,int maxflow){if (u==T||maxflow==0) return maxflow;int ans=0;for (int &i=cur[u];i;i=edge[i].pre)if (lev[edge[i].to]==lev[u]+1){int flow=dfs(edge[i].to,min(edge[i].cap-edge[i].flow,maxflow));maxflow-=flow;ans+=flow;edge[i].flow+=flow;edge[((i-1)^1)+1].flow-=flow;if (maxflow==0) return ans;}return ans;}void dinic(){int ans=0;while (bfs()){for (int i=1;i<=n+2;i++) cur[i]=head[i];ans+=dfs(S,inf);}}bool jud(){for (int i=head[S];i;i=edge[i].pre)if (edge[i].cap>edge[i].flow) return false;return true;}int main(){int tt=read();while (tt--){memset(head,0,sizeof(head));tot=0;memset(in,0,sizeof(in));n=read(),m=read();S=n+1,T=n+2;int u,v,w;for (int i=1;i<=m;i++){u=read(),v=read(),low[i]=read(),w=read();in[u]-=low[i],in[v]+=low[i];addedge(u,v,w-low[i]);}build();dinic();if (!jud()) printf("NO\n");else {printf("YES\n");for (int i=1;i<=m;i++)printf("%d\n",low[i]-edge[i*2].flow);}printf("\n");}return 0;}


0 0