Flow construction SGU - 176 有源汇有上下界最小流 二分法和回流法
/** 题目:Flow construction SGU - 176
链接:https://vjudge.net/problem/SGU-176
题意:
有源汇有上下界的最小流。
给定n个点,m个管道。每个管道给出u,v,z,c。u表示起点,v表示终点,z表示容量,如果c==1,那么表示还有下界为z。
如果c==0,表示没有下界。
求从1到n的最小流。
思路:
第一种做法:
转化为无源汇求超级源S到超级汇T的最大流flow1(此时从s出发的流和为flow1),然后讲t到s的边删掉(可以使流量等于容量,这样求t到s的最大流就不会经过他了。)
求t到s的最大流flow2(从s出发的流减少的量).是为了回流,因为原先求flow1的过程,是为了满足下界的可行流。这个在原图的可行流可能可以变得更小,通过回流使其缩小。
求t到s的最大流并不会影响原来附加边的流量。所以保证了是下界满足的可行流。
然后用flow1-flow2就是结果。 第二种做法:
构造无源汇有上下界的可行流做法,只不过t到s的边的上下界要改一下。
二分t到s的上界a,下界为0,如果是可行流最小的a便是最小流。如果是求最大流,那么就是二分t到s的下界a,上界无穷,如果是可行流,那么最大的a便是最大流。
不懂的看文档解释。https://wenku.baidu.com/view/0f3b691c59eef8c75fbfb35c.html 关于每次二分,处理一次最大流,那么下次在计算最大流的时候,难道又要重新建图?
反正是结构体存的,新加一个变量存储。下次直接从这个变量获取即可。注意t到s这条边的修改。或者最后面再加进去。 */ 第一种做法 #include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long LL;
const int N = ;///n+m=1365
int in[N];
int out[N];
struct Edge{
int from, to, cap, flow;
Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
struct Dinic{
int n, m, s, t;
vector<Edge> edges;
vector<int> G[N];
bool vis[N];
int d[N];
int cur[N]; void init(int n)
{
this->n = n;
for(int i = ; i <= n; i++) G[i].clear();
edges.clear();
} void AddEdge(int from,int to,int cap)
{
edges.push_back(Edge(from,to,cap,));
edges.push_back(Edge(to,from,,));
m = edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} bool BFS()
{
memset(vis, , sizeof vis);
queue<int> Q;
Q.push(s);
d[s] = ;
vis[s] = ;
while(!Q.empty())
{
int x = Q.front();
Q.pop();
for(int i = ; i < G[x].size(); i++)
{
Edge &e = edges[G[x][i]];
if(!vis[e.to]&&e.cap>e.flow)
{
vis[e.to] = ;
d[e.to] = d[x]+;
Q.push(e.to);
}
}
}
return vis[t];
} int DFS(int x,int a)
{
if(x==t||a==) return a;
int flow = , f;
for(int &i = cur[x]; i < G[x].size(); i++)
{
Edge& e = edges[G[x][i]];
if(d[x]+==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>)
{
e.flow += f;
edges[G[x][i]^].flow -= f;
flow += f;
a -= f;
if(a==) break;
}
}
return flow;
} int Maxflow(int s,int t)
{
this->s = s, this->t = t;
int flow = ;
while(BFS())
{
memset(cur, , sizeof cur);
flow += DFS(s,INF);
}
return flow;
}
};
int dw[N*N];
int main()
{
int n, m;
while(scanf("%d%d",&n,&m)==)
{
Dinic dinic;
dinic.init(n+);
int u, v, cap, flag;///1,n为普通源汇。
int s = , t = n+;///超级源汇。
memset(dw, , sizeof dw);
memset(in, , sizeof in);
memset(out, , sizeof out);
for(int i = ; i<m; i++){
scanf("%d%d%d%d",&u,&v,&cap,&flag);
if(flag==){
dw[i] = cap;
dinic.AddEdge(u,v,);
out[u]+=cap;
in[v]+=cap;
}else
{
dinic.AddEdge(u,v,cap); }
}
int ts;
dinic.AddEdge(n,,INF);
ts = dinic.edges.size()-;
int sum = ;
for(int i = ; i <= n; i++){
if(in[i]>out[i]){
dinic.AddEdge(s,i,in[i]-out[i]);
sum += in[i]-out[i];
}
if(in[i]<out[i]){
dinic.AddEdge(i,t,out[i]-in[i]);
}
}
int flow = dinic.Maxflow(s,t);
if(flow!=sum){
printf("Impossible\n"); continue;
}
dinic.edges[ts].cap = dinic.edges[ts].flow;///使其求n到1的最大流无法经过。
int flow2 = dinic.Maxflow(n,);///回流
printf("%d\n",flow-flow2);
for(int i = ; i < m; i++){
if(i==m-){
printf("%d\n",dinic.edges[*i].flow+dw[i]);
}else
{
printf("%d ",dinic.edges[*i].flow+dw[i]);
}
}
}
return ;
} 第二种做法 #include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long LL;
const int N = ;///n+m=1365
int in[N];
int out[N];
struct Edge{
int from, to, cap, flow;
Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
struct Dinic{
int n, m, s, t;
vector<Edge> edges;
vector<int> G[N];
bool vis[N];
int d[N];
int cur[N]; void init(int n)
{
this->n = n;
for(int i = ; i <= n; i++) G[i].clear();
edges.clear();
} void AddEdge(int from,int to,int cap)
{
edges.push_back(Edge(from,to,cap,));
edges.push_back(Edge(to,from,,));
m = edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} bool BFS()
{
memset(vis, , sizeof vis);
queue<int> Q;
Q.push(s);
d[s] = ;
vis[s] = ;
while(!Q.empty())
{
int x = Q.front();
Q.pop();
for(int i = ; i < G[x].size(); i++)
{
Edge &e = edges[G[x][i]];
if(!vis[e.to]&&e.cap>e.flow)
{
vis[e.to] = ;
d[e.to] = d[x]+;
Q.push(e.to);
}
}
}
return vis[t];
} int DFS(int x,int a)
{
if(x==t||a==) return a;
int flow = , f;
for(int &i = cur[x]; i < G[x].size(); i++)
{
Edge& e = edges[G[x][i]];
if(d[x]+==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>)
{
e.flow += f;
edges[G[x][i]^].flow -= f;
flow += f;
a -= f;
if(a==) break;
}
}
return flow;
} int Maxflow(int s,int t)
{
this->s = s, this->t = t;
int flow = ;
while(BFS())
{
memset(cur, , sizeof cur);
flow += DFS(s,INF);
}
return flow;
}
};
int dw[N*N];
int main()
{
int n, m;
while(scanf("%d%d",&n,&m)==)
{
Dinic dinic;
dinic.init(n+);
int u, v, cap, flag;///1,n为普通源汇。
int s = , t = n+;///超级源汇。
memset(dw, , sizeof dw);
memset(in, , sizeof in);
memset(out, , sizeof out);
for(int i = ; i<m; i++){
scanf("%d%d%d%d",&u,&v,&cap,&flag);
if(flag==){
dw[i] = cap;
dinic.AddEdge(u,v,);
out[u]+=cap;
in[v]+=cap;
}else
{
dinic.AddEdge(u,v,cap); }
}
int sum = ;
for(int i = ; i <= n; i++){
if(in[i]>out[i]){
dinic.AddEdge(s,i,in[i]-out[i]);
sum += in[i]-out[i];
}
if(in[i]<out[i]){
dinic.AddEdge(i,t,out[i]-in[i]);
}
}
Dinic Tdinic = dinic;
int flow;
int lo = , hi = INF, mid;
while(lo<hi){///最小流,二分上界,取最小值。
mid = (lo+hi)/;
dinic = Tdinic;
dinic.AddEdge(n,,mid);
flow = dinic.Maxflow(s,t);
if(flow!=sum){
lo = mid+;
}else
{
hi = mid;
}
}
if(hi==lo){
printf("Impossible\n"); continue;
}
printf("%d\n",hi);
dinic = Tdinic;///注意复原,因为此时的dinic不是最小流为hi的时候的。要重新计算。
dinic.AddEdge(n,,hi);
dinic.Maxflow(s,t);
for(int i = ; i < m; i++){
if(i==m-){
printf("%d\n",dinic.edges[*i].flow+dw[i]);
}else
{
printf("%d ",dinic.edges[*i].flow+dw[i]);
}
}
}
return ;
}
Flow construction SGU - 176 有源汇有上下界最小流 二分法和回流法的更多相关文章
- loj #117. 有源汇有上下界最小流
题目链接 有源汇有上下界最小流,->上下界网络流 注意细节,边数组也要算上后加到SS,TT边. #include<cstdio> #include<algorithm> ...
- LOJ.117.[模板]有源汇有上下界最小流(Dinic)
题目链接 有源汇有上下界最小流 Sol1. 首先和无源汇网络流一样建图,求SS->TT最大流: 然后连边(T->S,[0,INF]),再求一遍SS->TT最大流,答案为新添加边的流量 ...
- sgu 176 Flow construction(有源汇的上下界最小流)
[题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11025 [模型] 有源汇点的上下界最小流.即既满足上下界又满足 ...
- sgu176 Flow Construction【有源汇有上下界最小流】
同样是模板题. 首先将有源汇转换为无源汇,假设原来的源汇为st,我们加入的源汇为ST,那么我们应该从t到s连一条流量为+∞的边,使原来的st满足收支平衡,退化为普通节点. 分离必要边和其他边,从S到T ...
- sgu 176 有源汇有上下界的最小流模板题
/*参考博文:http://hi.baidu.com/dragon_eric123/item/82e259200ece744046996282 有上下界的有源最小流 */ #include<st ...
- 【 POJ - 3801】Crazy Circuits(有源汇、上下界最小流)
Description You’ve just built a circuit board for your new robot, and now you need to power it. Your ...
- bzoj 2502 清理雪道(有源汇的上下界最小流)
[题意] 有一个DAG,要求每条边必须经过一次,求最少经过次数. [思路] 有上下界的最小流. 边的下界为1,上界为无穷.构造可行流模型,先不加ts边跑一遍最大流,然后加上t->s的inf边跑 ...
- LOJ117 有源汇有上下界最小流(上下界网络流)
跑出可行流后从原来的汇点向原来的源点跑最大流,原图最小流=inf-maxflow.显然超源超汇的相关边对其也没有影响.原图最小流=可行流-原图新增流量,因为t向s流量增加相当于s向t流量减少.但为什么 ...
- Crazy Circuits HDU - 3157(有源汇有上下界最小流)
给出每条边的下界 求最小流 板题 提供两个板子代码 虽然这个题 第一个比较快 但在loj上https://loj.ac/problem/117 的板题 第一个1700+ms 第二个才600+ms ...
随机推荐
- mysql 5.7之后版本datatime 不允许设置 0000-00-00 00:00:00 的问题
打开mysql.ini配置文件 在mysqld下 加入sql-model验证规则即可 sql-mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FO ...
- Mac 清除/修改SSH的私钥密码
我之前在Mac下用命令ssh-keygen生成密钥,并且安全起见为密钥设置了密码,这样导致后来每次我git push时,都要输入一次密码: Enter pass phrase for /Users/z ...
- win下idea远程提交WordCount任务到HA集群
一,环境配置 1,修改win下的host文件:即C:\Windows\System32\drivers\etc\host中添加集群中机子的ip 2,win下hadoop,并为win的环境变量配置had ...
- JVM组成部分以及内存模型
一.JVM的组成部分 我们先把JVM这个虚拟机实现机制画出来,例如以下图所看到的: 从这个图中能够看到,JVM是执行在操作系统之上的,它与硬件没有直接的交互. 我们再来看下JVM有哪些组 成部分,例如 ...
- [Erlang]Erlang经常使用工具解说
原创文章,转载请注明出处:服务器非业余研究http://blog.csdn.net/erlib 作者Sunface 联系邮箱:cto@188.com 但凡有图形界面的都须要linux系统安装了wx图形 ...
- 蓝牙中文API文档
蓝牙是一种低成本.短距离的无线通信技术.对于那些希望创建个人局域网(PANs)的人们来说,蓝牙技术已经越来越流行了.每个个人局域网都在独立设备的周围被动态地创建,并且为蜂窝式电话和PDA等设备提供了自 ...
- Windows注册表中修改CMD默认路径
一.开启注册表“win键+R键”并输入regedit 二.在注册表项 HKEY_CURRENT_USER\ Software\ Microsoft\ Command Processor 新建一个项,并 ...
- 在k8s中的基本概念
在k8s中的基本概念 一.Pod1. podk8s下最重要也最基本的概念,由一个根容器Pause和许多用户业务容器组成,是容器的载体. 2. pod的yaml定义格式及字段 apiVersion: v ...
- Python中的__name__
python中if __name__ == '__main__': 的解析 经常会在代码的最下面看到if __name__ == '__main__':,现在就来介 绍一下它的作用. 模块是对象,并且 ...
- ZK框架笔记3、窗体组件
<window title="My First window" border="normal" width="200px" closa ...