网络流

网络流基础

允我心安 提交于 2019-12-03 14:37:29
感谢某个同学问我网络流问题的同学,让我在有生之年整理了一把网络流。 大部分资料来源于:洛谷暑期营的课件 一,一些关于网络流的概念 网络流图:一张有向连通图,有且只有一个点的入度为零,这个点称为源点,有且只有一个点的出度为零 这个点称为汇点,每个边有一个非负权值c称为这条边的容量。 容许流:在网络流图中,对于每条边 e = (i, j) 给定实数 fe ,如果满足 fe ≤ ce ; 对于任意 x ̸= S,T , ∑ e=(x,i) fe = ∑ e=(i,x) fe ;(流量平衡) ∑ e=(S,i) fe = ∑ e=(i,T) fe = W , 则这一组 f 称为 该网络的一个容许流,W 称为它的流量。 最大流:求一个容许流使得它的 W 最大,用通俗易懂的话说,最大流就是给源点赋一个数,你要让这个值能够通过 这张网络流图的路径流到汇点,你想让这个值尽量的大。 二,最大流算法 一类解决网络流求最大流问题的基本思想——Ford-Fulkerson 标号算法 该算法的核心思想为不断寻找增广路。 何为增广(源)路,就是找到一条从源点到汇点的路径,使得这条路径的流量不为零,就找到了一条增源路。 算法过程: 记录 ve = ce − fe ,为一条边的剩余可用容量。 对于每一条边 e = (i, j) ,增加一条 反向弧 e ′ = (j, i) ,ve’=0。 首先给 S 标号 (−,

POJ1087 A Plug for UNIX(网络流)

社会主义新天地 提交于 2019-12-03 07:09:22
在会议开始之前,你收集所有记者想要使用的设备,并尝试设置它们。你注意到有些设备使用没有插座的插头。你想知道这些设备是否来自建造这个房间时并不存在的国家。对于一些插座,有几个设备使用相应的插头。对于其他插座,没有使用相应插头的设备。 为了解决这个问题,你可以去附近的零件供应商店。该商店出售的适配器允许在不同类型的插座上使用一种类型的插头。此外,还允许将适配器插入到其他适配器中。该商店没有为所有可能的插头和插座组合提供适配器,但实际上他们有无限的供应。 输入 输入将包括一种情况。第一行包含一个正整数n (1 <= n <= 100),表示房间中插座的数量。接下来的n行列出了在房间中找到的容器类型。每个容器类型由最多24个字母数字字符组成的字符串组成。下一行包含一个正整数m (1 <= m <= 100),表示要插入的设备数量。接下来的m行每一行都列出了一个设备的名称,后面跟着它使用的插头类型(与它需要的插座类型相同)。设备名称是一个最多24个字母数字组成的字符串 字符。没有两个设备会有完全相同的名称。插头类型与设备名称之间用空格分隔。下一行包含一个正整数k (1 <= k <= 100),表示可用的适配器的不同种类的数量。接下来的k行描述了各种适配器,给出了适配器提供的插座类型,后面是空格,后面是插头类型。 输出 包含单个非负整数的行,它表示不能插入的设备的最小数目。 代码: 1 /

网络流基础

匿名 (未验证) 提交于 2019-12-03 00:17:01
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define maxn 10010 7 #define INF 2147483647 8 9 using namespace std; 10 11 struct node 12 { 13 int ed,nxt,len; 14 }; 15 node edge[maxn*20]; 16 int n,m,cnt=-1,first[maxn],S,T,ans; 17 int pre_u[maxn],pre_e[maxn],flow[maxn]; 18 bool vis[maxn]; 19 20 inline void add_edge(int s,int e,int d) 21 { 22 ++cnt; 23 edge[cnt].ed=e; 24 edge[cnt].len=d; 25 edge[cnt].nxt=first[s]; 26 first[s]=cnt; 27 return; 28 } 29 30 inline bool bfs(int s,int t) 31 { 32 queue <int> q; 33 memset(vis,false,sizeof(vis)); 34

网络流24题

匿名 (未验证) 提交于 2019-12-03 00:11:01
马上就国庆了,翻了就是初赛。偶有怠惰,是复习联赛略枯燥的故。于是挖新坑,刷刷有趣的算法自慰。(肯定不会咕咕咕的啦,吧) 来源:博客园 作者: 邱涵的秘密基地 链接:https://www.cnblogs.com/bingoyes/p/11585407.html

网络流24题の详解

匿名 (未验证) 提交于 2019-12-03 00:02:01
把网络流24题刷完我就算萌新了。 (持续更新直到刷完为止) \(1.\) 洛谷P2756 飞行员配对方案问题 题意:派出最多架的飞机,并且每架飞机上都是一个英国飞行员和外籍飞行员 分析:经典的二分图匹配问题,将英国飞行员当做二分图的左部,外籍飞行员当做二分图的右部。可以用匈牙利算法求解,但这里使用网络流(最大流)。 考虑如何建图: 设立一个源点 \(st\) ,一个汇点 \(ed\) 。 \(I.\) 让源点 \(st\) 向二分图的左部建一条流量为 \(1\) 的边, \(II.\) 让二分图的右部向汇点 \(ed\) 建一条流量为 \(1\) 的边, \(III.\) 如果英国飞行员 \(u\) 可以和外籍飞行员 \(v\) 配合,那么 \(u\) 和 \(v\) 建一条流量为 \(1\) 的边。 最后跑一遍最大流即可得到最大匹配数。 如何输出配对方案: 遍历所有的英国飞行员所连的边,如果此边 \((u,v)\) 流量不是 \(1\) 而是 \(0\) 说明 \((u,v)\) 配对。注意源点向英国飞行员所连的边流量会为0,但此时不应输出。 #include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,

【网络流24题】魔术球问题

匿名 (未验证) 提交于 2019-12-02 23:49:02
以珠子为点,满足条件就两两连边 那么就是让你求n条路径最多能覆盖多少节点。 众所周知,最小边覆盖=点总数-最大匹配 不会看这里 Link 于是拆点跑二分图即可 大概就是S向x连边 满足条件的点k向x'连边 x'向T连边 有两种方式 1.我们轮流加点,每次在残量网络跑最大流就可以了 2.我们二分答案,每次重新跑最大流 实测前一种更快。 QwQ 输出答案就看哪条边的流量跑满了。 /* @Date : 2019-07-20 15:12:45 @Author : Adscn (adscn@qq.com) @Link : https://www.cnblogs.com/LLCSBlog */ #include<bits/stdc++.h> using namespace std; #define IL inline #define RG register #define gi getint() #define gc getchar() #define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout) IL int getint() { RG int xi=0; RG char ch=gc; bool f=0; while(ch<'0'||ch>'9')ch=='-'?f=1:f,ch=gc; while(ch>='0'

上下界网络流

匿名 (未验证) 提交于 2019-12-02 23:49:02
$orz$ $zhhx$ $orz$ $AYSN$ 无源汇可行流:每条边取$L[i]$+最大流调整 有源汇可行流:$E + (T,S,INF)$+无源汇可行流 有源汇最小流:有源汇可行流(去掉$INF$边)- $T \rightarrow S$最大流 有源汇最大流:有源汇可行流(去掉$INF$边)+ $S \rightarrow T$最大流

[洛谷P2472] [SCOI2007]蜥蜴

匿名 (未验证) 提交于 2019-12-02 23:49:02
蜥蜴 一道网络流,先来分析一下问题: 在一个 \(r*c\) 的图中分布了一些数,其他地方都用 \(0\) 填充,我们分别从指定的一些数出发,每次可以移动到周围距离为 \(d\) 以内的数上(或图外),原来的数会被 \(-1\) ,任何时候数不能为负。各个数走法之间互相影响。问至多有多少个数出发能到达图外? 把这个题的限制条件列出来一下吧: 每个石柱只能站一只蜥蜴 每个石柱最多被经过其高度次 石柱与石柱之间,石柱与图边界之间要距离小于等于 \(d\) 才能到达 首先我的角度是以每个石柱本身的限制条件入手。我们知道一个高度为 \(h\) 的石柱最多可以被经过 \(h\) 次(显然,蜥蜴是不走回头路的,因为这是对资源的浪费),而网络流的基本性质之一,是每条边最多将其上限流满(相当于有一个上限),那么可以考虑将石柱的高度作为网络流建图边上的限制。但是每个石柱是一个点,怎么办呢,我们就考虑把每个石柱拆点,把编号为 \(i\) 的点拆成 \(i\) 和 \(i + r * c\) ,然后把流入这个点的边全部接到 \(i\) 上,流出这个点的边全部接到 \(i+r*c\) 上,把限制加在两点之间的连边上(流量为 \(h\) )。这是对于石柱的处理,也是我认为这个问题中最关键的一步。 剩下的就比较好办了。 对于“每个石柱只能站一只蜥蜴”的限制条件,将“只能站一只”作为上界

【网络流24题】餐巾计划问题

匿名 (未验证) 提交于 2019-12-02 23:49:02
建边有技巧啊,要拆点。 网络流建边的核心规律就是 多做题 一定是从源点到汇点,根据此构建模型即可。 \(dinic\) 实现最小费用流 /* @Date : 2019-07-16 11:10:42 @Author : Adscn (adscn@qq.com) @Link : https://www.cnblogs.com/LLCSBlog */ #include<bits/stdc++.h> using namespace std; #define IL inline #define RG register #define gi getint() #define gc getchar() #define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout) IL int getint() { RG int xi=0; RG char ch=gc; bool f=0; while(ch<'0'|ch>'9')ch=='-'?f=1:f,ch=gc; while(ch>='0'&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc; return f?-xi:xi; } template<typename T> IL void pi(T k,char ch=0) { if(k<0)k=-k

网络流

匿名 (未验证) 提交于 2019-12-02 23:48:02
网络流=带反悔的贪心。――517 个人认为网络流=最大流dinic/费用流板子+玄学意会建图。 对于每条边 \((u,v,w)\) ,建一条相应的反向边 \((v,u,0)\) 。 算法执行时,先从源点s bfs,看看到t最多能流多少,对于每个节点记录它的前驱节点,如果到t的流量不为0,那么从t回溯回s,将每条边的容量减去流量,其反向边的容量加上流量,然后把答案加上所有回溯到的边的流量;否则停止执行,返回结果。最坏复杂度 \(O(nm^2)\) 。 #include<bits/stdc++.h> #define maxn 10005 #define maxm 100005 #define INF 1050000000 using namespace std; template<typename tp> void read(tp& x){ x=0; char c=getchar(); bool sgn=0; while((c<'0'||c>'9')&&c!='-')c=getchar(); if(c=='-')sgn=1,c=getchar(); while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar(); if(sgn)x=-x; } template<typename tp> void write(tp x){ if(x<0