题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=176

题意:给出一个有向图,边有边权。对于边有要求,要求有些边的流量恰好等于容量,其他边的流量要不大于其容量。在该要求下求最小流。1号点为源点,n号点为汇点。

思路:有上下限最小流。两种方法:

(1)构建的新图D和上面的D是一样的。也是先求S到T的最大流,此时记录<t,s>边的流量A,然后删掉边<t,s>,接着求t到s的最大流B,则答案为A-B。此时A-B有可能为0,原因是这个图本来最小流为0,由于有环的存在这个图可以自给自足,此时增加S到s的边<S,s,B-A>,再跑S到t(此时是原来图的汇点t)的最大流。这样,每条边的流量加上下限就是每条边的实际流量。

(2)二分t到s的上限。x=in[i]-out[i],x>=0,连边<S,i,x>,sum+=x,否则<i,T,-x>。求S到T的最大流,大于等于sum则可行。

#include <iostream>
#include <string.h>
#include <stdio.h>
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;struct node
{int x,y,b,c;
};struct Node
{int v,cap,flow,next;Node(){}Node(int _v,int _cap,int _flow,int _next){v=_v;cap=_cap;flow=_flow;next=_next;}
};const int INF=1000000000;
Node edges[120005];
node info[10005];
int n,m,s,t,S,T,head[1005],e;
int num[1005],h[1005],curedge[1005],pre[1005];void Add(int u,int v,int cap)
{edges[e]=Node(v,cap,0,head[u]);head[u]=e++;edges[e]=Node(u,0,0,head[v]);head[v]=e++;
}int Maxflow(int s,int t,int n)
{int ans=0,i,k,x,d,u;memset(num,0,sizeof(num));memset(h,0,sizeof(h));for(i=0;i<=n;i++) curedge[i]=head[i];num[n]=n;u=s;while(h[u]<n){if(u==t){d=INF+1;for(i=s;i!=t;i=edges[curedge[i]].v) if(d>edges[curedge[i]].cap)k=i,d=edges[curedge[i]].cap;for(i=s;i!=t;i=edges[curedge[i]].v){x=curedge[i];edges[x].cap-=d;edges[x].flow+=d;edges[x^1].cap+=d;edges[x^1].flow-=d;}ans+=d;u=k;}for(i=curedge[u];i!=-1;i=edges[i].next) if(edges[i].cap>0&&h[u]==h[edges[i].v]+1)break;if(i!=-1){curedge[u]=i;pre[edges[i].v]=u;u=edges[i].v;}else{if(--num[h[u]]==0) break;curedge[u]=head[u];for(x=n,i=head[u];i!=-1;i=edges[i].next) if(edges[i].cap>0&&h[edges[i].v]<x)x=h[edges[i].v];h[u]=x+1;num[h[u]]++;if(u!=s) u=pre[u];}}return ans;
}int in[105],out[105];int main()
{memset(head,-1,sizeof(head));e=0;int ans1,ans2,ans,i,sum=0;scanf("%d%d",&n,&m);if(n==0){puts("Impossible");return 0;}s=1;t=n;S=n+1;T=n+2;for(i=1;i<=m;i++){scanf("%d%d%d%d",&info[i].x,&info[i].y,&info[i].b,&info[i].c);if(info[i].c){sum+=info[i].b;in[info[i].y]+=info[i].b;out[info[i].x]+=info[i].b;Add(info[i].x,info[i].y,0);}else Add(info[i].x,info[i].y,info[i].b);}for(i=1;i<=n;i++){Add(S,i,in[i]);Add(i,T,out[i]);}Add(t,s,INF);if(Maxflow(S,T,n+2)!=sum){puts("Impossible");return 0;}ans1=edges[head[t]^1].cap;edges[head[t]].cap=0;edges[head[t]^1].cap=0;ans2=Maxflow(t,s,n+2);ans=ans1-ans2;if(ans<0){edges[head[t]].cap=0;edges[head[t]^1].cap=0;edges[e]=Node(s,-ans,0,head[S]);head[S]=e++;Maxflow(S,t,n+2);ans=0;}printf("%d\n",ans);for(i=1;i<=m;i++) printf(i==1?"%d":" %d",edges[i+i-1].cap+info[i].b*info[i].c);puts("");return 0;
}

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <map>#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)>=0?(x):-(x))
#define i64 long long
#define u32 unsigned int
#define u64 unsigned long long
#define clr(x,y) memset(x,y,sizeof(x))
#define CLR(x) x.clear()
#define ph(x) push(x)
#define pb(x) push_back(x)
#define Len(x) x.length()
#define SZ(x) x.size()
#define PI acos(-1.0)
#define sqr(x) ((x)*(x))
#define MP(x,y) make_pair(x,y)
#define EPS 1e-9#define FOR0(i,x) for(i=0;i<x;i++)
#define FOR1(i,x) for(i=1;i<=x;i++)
#define FOR(i,a,b) for(i=a;i<=b;i++)
#define FORL0(i,a) for(i=a;i>=0;i--)
#define FORL1(i,a) for(i=a;i>=1;i--)
#define FORL(i,a,b)for(i=a;i>=b;i--)
using namespace std;void RD(int &x){scanf("%d",&x);}
void RD(u32 &x){scanf("%u",&x);}
void RD(double &x){scanf("%lf",&x);}
void RD(int &x,int &y){scanf("%d%d",&x,&y);}
void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}
void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}
void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}
void RD(int &x,int &y,int &z,int &t){scanf("%d%d%d%d",&x,&y,&z,&t);}
void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}
void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}
void RD(char &x){x=getchar();}
void RD(char *s){scanf("%s",s);}
void RD(string &s){cin>>s;}void PR(int x) {printf("%d\n",x);}
void PR(int x,int y) {printf("%d %d\n",x,y);}
void PR(i64 x) {printf("%lld\n",x);}
void PR(u32 x) {printf("%u\n",x);}
void PR(double x) {printf("%.5lf\n",x);}
void PR(char x) {printf("%c\n",x);}
void PR(char *x) {printf("%s\n",x);}
void PR(string x) {cout<<x<<endl;}struct Node
{int u,v,cap,flow,next;
};const int INF=1000000000;
Node edges[120005];
int n,m,s,t,head[1005],e;
int num[1005],h[1005],curedge[1005],pre[1005];void add(int u,int v,double cap)
{edges[e].u=u;edges[e].v=v;edges[e].cap=cap;edges[e].flow=0.0;edges[e].next=head[u];head[u]=e++;
}void Add(int u,int v,double cap)
{add(u,v,cap);add(v,u,0.0);
}int Maxflow(int s,int t,int n)
{int ans=0,i,k,x,d,u;memset(num,0,sizeof(num));memset(h,0,sizeof(h));for(i=0;i<=n;i++) curedge[i]=head[i];num[n]=n;u=s;while(h[u]<n){if(u==t){d=INF+1;for(i=s;i!=t;i=edges[curedge[i]].v) if(d>edges[curedge[i]].cap)k=i,d=edges[curedge[i]].cap;for(i=s;i!=t;i=edges[curedge[i]].v){x=curedge[i];edges[x].cap-=d;edges[x].flow+=d;edges[x^1].cap+=d;edges[x^1].flow-=d;}ans+=d;u=k;}for(i=curedge[u];i!=-1;i=edges[i].next) if(edges[i].cap>0&&h[u]==h[edges[i].v]+1)break;if(i!=-1){curedge[u]=i;pre[edges[i].v]=u;u=edges[i].v;}else{if(--num[h[u]]==0) break;curedge[u]=head[u];for(x=n,i=head[u];i!=-1;i=edges[i].next) if(edges[i].cap>0&&h[edges[i].v]<x)x=h[edges[i].v];h[u]=x+1;num[h[u]]++;if(u!=s) u=pre[u];}}return ans;
}struct Info
{int u,v,b,c;void read(){RD(u,v,b,c);if(c==0) c=b,b=0;else c=b;}
};Info a[10005];
int in[105],out[105];int OK(int mid)
{clr(head,-1); e=0;clr(in,0),clr(out,0);int i,sum=0,x;a[m+1].u=n; a[m+1].v=1;a[m+1].b=0; a[m+1].c=mid;FOR1(i,m+1){in[a[i].v]+=a[i].b;out[a[i].u]+=a[i].b;Add(a[i].u,a[i].v,a[i].c-a[i].b);}int S=0,T=n+1;FOR1(i,n){x=in[i]-out[i];if(x>=0) Add(S,i,x),sum+=x;else Add(i,T,-x);}return Maxflow(S,T,T+1)>=sum;
}int main()
{RD(n,m);int i;FOR1(i,m) a[i].read();int low=0,high=INF,mid;while(low<=high){mid=(low+high)>>1;if(OK(mid)) high=mid-1;else low=mid+1;}int ans;if(high>=0&&OK(high)) ans=high;else if(OK(low)) ans=low;else ans=-1;if(ans==-1){puts("Impossible");return 0;}PR(ans);FOR1(i,m){if(i!=1) putchar(' ');printf("%d",edges[i+i-1].cap+a[i].b);}puts("");return 0;
}

  

SGU 176 Flow construction(有上下限的最小流)相关推荐

  1. SGU-176 Flow construction 有上下界的最小流

    这里参看了大牛的解题思路,学习了很多.原来上下界流的求法是这么的灵活,尤其我是用的临界表存储的边,删除更新很不方便. http://www.shuizilong.com/house/archives/ ...

  2. 【有源汇点上下界最小流】[SGU176]Flow construction

    题目大意 给出N个点,M条有向边 如果有向边的标号是1的话,就表示该边的上界下界都为容量 如果有向边的标号为0的哈,表示该边的下界为0,上界为容量 现在问,从1到N的最小流是多少,并输出每条边的流量 ...

  3. 有上下界网络流 ---- P4843 清理雪道(DAG图上最小路径重复边覆盖)【模板】有源汇上下界最小流

    题目链接 题目大意: 解题思路: 首先我们发现对于每条边至少要覆盖一次,最多覆盖无数次 那么就有点像上下界网络流了[1,INF][1,INF][1,INF]的限制关系 跑一边最小流就可以了!! #in ...

  4. HDU 3157 Crazy Circuits(有源汇上下界最小流)

    HDU 3157 Crazy Circuits 题目链接 题意:一个电路板,上面有N个接线柱(标号1~N),还有两个电源接线柱 + -.给出一些线路,每一个线路有一个下限值求一个能够让全部部件正常工作 ...

  5. BZOJ 2502: 清理雪道 [最小流]

    2502: 清理雪道 题意:任意点出发任意次每条边至少经过一次最小花费. 下界1,裸最小流.... #include <iostream> #include <cstdio> ...

  6. LOJ - #117. 有源汇有上下界最小流(有源汇有上下界的最小流)

    题目链接:点击查看 题目大意:给出一个 n 个点和 m 条边的有向图,每条边都有一个流量限制 [ lower , upper ],给定源点 s 和汇点 t ,求出源点到汇点的最小流 题目分析:参考我的 ...

  7. POJ 3801/HDU 3157 Crazy Circuits | 有下界的最小流

    题目: POJ最近总是炸 所以还是用HDU吧http://acm.hdu.edu.cn/showproblem.php?pid=3157 题解: 题很长,但其实就是给个有源汇带下界网络流(+是源,-是 ...

  8. 图论:有源汇有上下界最小流

    这次就是最小流了 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll I ...

  9. 有汇源上下界最大流和最小流

    有汇源上下界最大流 有源汇上下界最大流最小流理解 题目 理解 #include<bits/stdc++.h> using namespace std; const int N=610,M= ...

  10. [BZOJ2502]清理雪道解题报告|带下界的最小流

    滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机,每次飞 ...

最新文章

  1. 区块链与边缘计算(1)基本概念
  2. mybatis配置问题
  3. nodejs TCP server和TCP client如何进行数据交互
  4. .net 微服务实践
  5. hashset java_Java HashSet clear()方法与示例
  6. python学习之random
  7. Activity生命周期Android,横屏切换不重新创建Activity, Activity的四种launchMode
  8. 互联网企业架构初期选择--初期技术选型
  9. turbo c是什么?
  10. 5款创业在线学习的工具
  11. 国企计算机岗位职称申请,在国企工作如何评定职称
  12. 计算机毕设 SpringBoot 校园志愿者管理系统 志愿者管理系统 志愿者信息管理系统Java Vue MySQL数据库 远程调试 代码讲解
  13. 限制性立方样条(Restricted Cubic Spline)
  14. 雅可比(Jacobi)及高斯-塞德尔(Gauss_Seidel)迭代法求解线性方程组的matlab现实
  15. Win8.1 安装NLTK及nltk数据
  16. android逆向分析腾讯微视研究无限循环视频嵌套滑动不中断的实现方式
  17. 3dvary灯光材质为什么不亮_3dmax灯光教程灯光打出来太假?不真实?杂点?曝光?原因都在这儿呢...
  18. 最新高频Java面试题目分享,分布式ID(数据库多主模式
  19. Typora自动上传图床配置
  20. 经典的三角形软件测试用例

热门文章

  1. Flink CDC + Hudi + Hive + Presto 构建实时数据湖最佳实践
  2. Android TV开发总结【适配】
  3. c语言spoc期末考试及答案,MOOC-SPOC测试题(部分答案)(至数组一章)-C语言-宣城校区2016年.docx...
  4. java xss 参数_JAVA 重写HttpServletRequest的获取参数防止xss攻击
  5. 奥鹏2019计算机应用基础1,奥鹏东师2019年秋季(计算机应用基础)离线考核(仅供参考).docx...
  6. java基本操作-2
  7. visual studio怎么编译python_我的计算机上的Python使用哪个版本的Visual Studio进行编译?...
  8. 会议室预约微信小程序推荐_又是BYPASS!微信小程序预约 YEEZY BOOST 350 V2 只要3S就能搞定!...
  9. 32位crc校验码程序_基于FPGA的CRC校验码生成器设计
  10. mysql实现主从复制的方式_mysql实现主从复制、读写分离的配置方法(二)