有源汇上下界最小流[模板]
发布日期:2021-06-30 10:20:46
浏览次数:3
分类:技术文章
本文共 2352 字,大约阅读时间需要 7 分钟。
这 只 是 其 中 一 种 做 法 这只是其中一种做法 这只是其中一种做法(我暂时还没有理解,只是先放个模板而已)
首 先 还 是 根 据 下 界 来 建 图 , 原 图 源 点 s , 汇 点 t 首先还是根据下界来建图,原图源点s,汇点t 首先还是根据下界来建图,原图源点s,汇点t
然 后 因 为 流 量 守 恒 , 新 建 超 级 源 s 1 和 超 级 汇 t 1 向 各 个 点 连 边 然后因为流量守恒,新建超级源s1和超级汇t1向各个点连边 然后因为流量守恒,新建超级源s1和超级汇t1向各个点连边
跑 一 遍 s 1 到 t 1 的 最 大 流 ( 也 就 是 可 行 流 ) 跑一遍s1到t1的最大流(也就是可行流) 跑一遍s1到t1的最大流(也就是可行流)
然 后 t 到 s 连 一 条 流 量 i n f 的 边 然后t到s连一条流量inf的边 然后t到s连一条流量inf的边
再 跑 一 遍 s 1 到 t 1 的 最 大 流 再跑一遍s1到t1的最大流 再跑一遍s1到t1的最大流
此 时 t 到 s 的 那 条 边 的 反 向 弧 流 量 就 是 最 小 流 此时t到s的那条边的反向弧流量就是最小流 此时t到s的那条边的反向弧流量就是最小流
#includeusing namespace std;const int maxn=2e5+10;const int inf=1e9;int n,m,s,t;struct edge{ int to,flow,nxt;}d[maxn]; int head[maxn],cnt=1; void add(int u,int v,int flow){ d[++cnt]=(edge){v,flow,head[u]},head[u]=cnt; d[++cnt]=(edge){u,0,head[v]},head[v]=cnt;}int dis[maxn],in[maxn],up[maxn],down[maxn],g[maxn];bool bfs(int s,int t){ memset(dis,0,sizeof(dis)); dis[s]=1; queue q; q.push(s); while( !q.empty() ) { int u=q.front(); q.pop(); for(int i=head[u];i;i=d[i].nxt ) { int v=d[i].to; if( dis[v]==0&&d[i].flow ) { dis[v]=dis[u]+1; if( v==t ) return true; q.push( v ); } } } return false;}int dinic(int u,int t,int flow){ if( u==t ) return flow; int res=flow; for(int i=head[u];i&&res;i=d[i].nxt ) { int v=d[i].to; if( dis[v]==dis[u]+1&&d[i].flow ) { int temp=dinic(v,t,min(res,d[i].flow) ); if( temp==0 ) dis[v]=0; d[i].flow-=temp,d[i^1].flow+=temp; res-=temp; } } return flow-res;}int maxflow(int s,int t){ int ans=0; while( bfs(s,t) ) ans+=dinic(s,t,inf); return ans;}int vis[109][109],row[109],col[109];int main(){ int k; cin >> n >> m >> k; for(int i=1;i<=n;i++) cin >> row[i]; for(int j=1;j<=m;j++) cin >> col[j]; while( k-- ) { int l,r; cin >> l >> r; vis[l][r]=1; } int s=0,t=n+m+1; int s1=t+1,t1=t+2; for(int i=1;i<=n;i++) { int temp=0; for(int j=1;j<=m;j++) { if( vis[i][j] ) continue; //第i行向第j列连边 add(i,j+n,1); temp++; } //下界是row[i],上界是temp add(s,i,temp-row[i]); in[s]-=row[i],in[i]+=row[i]; } for(int i=1;i<=m;i++) { int temp=0; for(int j=1;j<=n;j++) if( !vis[j][i] ) temp++; add(i+n,t,temp-col[i]); in[i+n]-=col[i],in[t]+=col[i]; } int sumn=0; for(int i=0;i<=n+m+1;i++) if( in[i]>0 ) add(s1,i,in[i] ),sumn+=in[i]; else add( i,t1,-in[i] ); int ans=maxflow(s1,t1); add(t,s,inf); int now=maxflow(s1,t1); cout << d[cnt].flow;}
转载地址:https://issue-is-vegetable.blog.csdn.net/article/details/108243502 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
网站不错 人气很旺了 加油
[***.192.178.218]2024年04月20日 06时13分27秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Struts2高危漏洞修复方案(S2-016/S2-017)
2019-04-30
oracle相关查询指标
2019-04-30
Linux下用SCP无需输入密码传输文件
2019-04-30
Linux下tar命令exclude选项排除指定文件或目录
2019-04-30
su -c
2019-04-30
linux gzip压缩/解压缩*.gz文件
2019-04-30
linux设置服务器禁止或开启ping包
2019-04-30
linux修改SSH默认22端口的方法
2019-04-30
mysql 设置max_allowed_packet 大小
2019-04-30
perl语言hello world程序
2019-04-30
perl中的特殊字符
2019-04-30
perl替换数组元素
2019-04-30
perl中的特殊变量$[
2019-04-30
perl中的函数,传参
2019-04-30
登录验证码使用汉字的方法
2019-04-30
easyui项目主页面架构搭建
2019-04-30
easyui修改回显使用form("load",row)
2019-04-30
mysql解决中文乱码问题
2019-04-30
点击劫持漏洞:使用X-Frame-Options 解决方法(应用tomcat)
2019-04-30