二分图匹配与网络流问题
信息学竞赛中的的最大流与最小割

信息学竞赛中的的最大流与最小割在信息学竞赛中的最大流与最小割信息学竞赛是一项旨在提高学生信息学知识和解决问题能力的竞赛活动。
其中,最大流与最小割是解决网络流问题的重要算法。
本文将对最大流与最小割的基本概念、算法及其在信息学竞赛中的应用进行介绍。
一、最大流与最小割的概念在图论中,最大流与最小割是两个相互关联的概念。
最大流指在一个网络中,从源点到汇点的最大可行流量;而最小割是指将网络切割成两个部分,使得从源点到汇点的流量最小。
最大流问题和最小割问题是互为对偶的,可以通过计算最大流来求解最小割,或者通过计算最小割来求解最大流。
二、最大流与最小割的算法1. Ford-Fulkerson算法Ford-Fulkerson算法是最早被提出的最大流算法之一。
算法通过不断在残留网络中找增广路径来增加流量,直到无法找到增广路径为止。
Ford-Fulkerson算法的时间复杂度取决于路径的选择,可以达到O(EF),其中E是边的数量,F是最大流的大小。
2. Edmonds-Karp算法Edmonds-Karp算法是基于Ford-Fulkerson算法的一种实现,它使用BFS寻找最短增广路径。
由于BFS保证了路径长度的最小化,Edmonds-Karp算法的时间复杂度为O(VE^2),在稀疏图中效果明显优于Ford-Fulkerson算法。
3. Dinic算法Dinic算法是一种高效的最大流算法,它使用了分层图和阻塞流的思想。
分层图是通过BFS构建的,用于寻找增广路径;而阻塞流用于快速计算最大流。
Dinic算法的时间复杂度为O(V^2E)。
三、最大流与最小割在信息学竞赛中的应用最大流与最小割在信息学竞赛中的应用非常广泛。
例如,可以用最大流算法解决二分图匹配问题,即将图中的点分为两个集合,使得任意相邻的两个点属于不同的集合,并找到最大的匹配数量。
最大流还可用于解决任务分配、资源分配等问题。
此外,最小割在信息学竞赛中也有重要的应用。
图论:二分图多重匹配

图论:⼆分图多重匹配使⽤最⼤流和费⽤流解决⼆分图的多重匹配之前编辑的忘存了好⽓啊。
本来打算学完⼆分图的乱七⼋糟的匹配之后再去接触⽹络流的,提前撞到了之前我们说的⼆分图最⼤匹配和⼆分图最⼤权匹配有⼀个特点,那就是没个点只能与⼀条边相匹配如果规定⼀个点要与L条边相匹配,这样的问题就是⼆分图的多重匹配问题然后根据边是否带权重,⼜可以分为⼆分图最⼤多重匹配和⼆分图最⼤权多重匹配(⼆分图多重最佳完美匹配)⾸先给出⼆分图多重最⼤匹配的做法:在原图上建⽴源点S和汇点T,S向每个X⽅点连⼀条容量为该X⽅点L值的边,每个Y⽅点向T连⼀条容量为该Y⽅点L值的边原来⼆分图中各边在新的⽹络中仍存在,容量为1(若该边可以使⽤多次则容量⼤于1),求该⽹络的最⼤流,就是该⼆分图多重最⼤匹配的值然后给出⼆分图多重最优匹配(⼆分图多重最⼤权匹配)的做法:在原图上建⽴源点S和汇点T,S向每个X⽅点连⼀条容量为该X⽅点L值、费⽤为0的边,每个Y⽅点向T连⼀条容量为该Y⽅点L值、费⽤为0的边原来⼆分图中各边在新的⽹络中仍存在,容量为1(若该边可以使⽤多次则容量⼤于1),费⽤为该边的权值。
求该⽹络的最⼤费⽤最⼤流,就是该⼆分图多重最优匹配的值这道题⾥⾯,⼀共有X⽅点这么多的电影,每个电影需要拍摄多少天就是对应的X⽅点L值,然后每⼀天是⼀个Y⽅点,由于每⼀天只能拍摄⼀部电影,所有Y⽅点的L值均为1下⾯介绍⼀下实现:int n,sum,cnt,ans;int g[maxn],cur[maxn];int str[25][10];struct Edge{int u,v,next,cap,flow;}e[maxm];这⾥⾯的cur数组是g数组的临时数组str⽤来保存每⼀个电影可以在哪⼀天拍摄Edge是⽹络流图⾥⾯的边void addedge(int u,int v,int c){e[++cnt].u=u;e[cnt].v=v;e[cnt].cap=c;e[cnt].flow=0;e[cnt].next=g[u];g[u]=cnt;e[++cnt].u=v;e[cnt].v=u;e[cnt].cap=0;e[cnt].flow=0;e[cnt].next=g[v];g[v]=cnt;}建图的时候,注意怎么赋值的接下来根据题意建图:for(int i=1;i<=n;i++){for(int j=1;j<=7;j++)scanf("%d",&str[i][j]);scanf("%d%d",&d,&w);sum+=d;addedge(0,i,d); //容量为需要多少天for(int j=1;j<=7;j++)for(int k=0;k<w;k++)if(str[i][j]) addedge(i,20+k*7+j,1);}for(int i=21;i<=370;i++) addedge(i,371,1);ans=maxflow(0,371);0为源点,371为汇点sum最后进⾏⼀个统计,和源点出发的最⼤流量进⾏⽐较,如果相等,说明电影排的开然后是求最⼤流的⼀个板⼦int maxflow(int st,int ed){int flowsum=0;while(bfs(st,ed)){memcpy(cur,g,sizeof(g));flowsum+=dfs(st,ed,INF);//cout<<"#"<<flowsum<<" ";}return flowsum;}具体的DFS和BFS这⾥不作为重点,以后再说下⾯给出完整的实现:1 #include<cstdio>2 #include<cstring>3 #include<algorithm>4using namespace std;5const int INF=1000000000;6const int maxn=1005;7const int maxm=20005;8int n,sum,cnt,ans;9int g[maxn],cur[maxn];10int str[25][10];11struct Edge{int u,v,next,cap,flow;}e[maxm];12void addedge(int u,int v,int c)13 {14 e[++cnt].u=u;e[cnt].v=v;e[cnt].cap=c;15 e[cnt].flow=0;e[cnt].next=g[u];g[u]=cnt;1617 e[++cnt].u=v;e[cnt].v=u;e[cnt].cap=0;18 e[cnt].flow=0;e[cnt].next=g[v];g[v]=cnt;19 }20int q[maxn],vis[maxn],d[maxn];21bool bfs(int st,int ed)22 {23 memset(q,0,sizeof(q));24 memset(vis,0,sizeof(vis));25 memset(d,-1,sizeof(d));26 vis[st]=1;d[st]=0;27int h=0,t=1;28 q[t]=st;29while(h!=t)30 {31 h=h%maxn+1;32int u=q[h];33for(int tmp=g[u];tmp;tmp=e[tmp].next)34 {35if(!vis[e[tmp].v]&&e[tmp].cap>e[tmp].flow)36 {37 vis[e[tmp].v]=1;38 d[e[tmp].v]=d[u]+1;39if(e[tmp].v==ed) return true;40 t=t%maxn+1;41 q[t]=e[tmp].v;42 }43 }44 }45return false;46 }47int getpair(int x)48 {49if(x%2==0)50return x-1;51else return x+1;52 }53int dfs(int x,int ed,int a)54 {55if(x==ed||a==0) return a;56int flow=0,f;57for(int tmp=cur[x];tmp;tmp=e[tmp].next)58 {59if(d[e[tmp].v]==d[x]+1&&(f=dfs(e[tmp].v,ed,min(a,e[tmp].cap-e[tmp].flow)))>0)60 {61 e[tmp].flow+=f;62 e[getpair(tmp)].flow-=f;63 a-=f;64 flow+=f;65if(a==0) break;66 }67 }68return flow;69 }70int maxflow(int st,int ed)71 {72int flowsum=0;73while(bfs(st,ed))74 {75 memcpy(cur,g,sizeof(g));76 flowsum+=dfs(st,ed,INF);77//cout<<"#"<<flowsum<<" ";78 }79return flowsum;8081 }82void init()83 {84 sum=cnt=0;85 memset(g,0,sizeof(g));86 }87int main()88 {89int T,d,w;90 scanf("%d",&T);91while(T--)92 {93 init();94 scanf("%d",&n);95for(int i=1;i<=n;i++)96 {97for(int j=1;j<=7;j++)98 scanf("%d",&str[i][j]);99 scanf("%d%d",&d,&w);100 sum+=d;101 addedge(0,i,d); //容量为需要多少天102for(int j=1;j<=7;j++)103for(int k=0;k<w;k++)104if(str[i][j]) addedge(i,20+k*7+j,1);105 }106for(int i=21;i<=370;i++) addedge(i,371,1);107 ans=maxflow(0,371);108if(ans==sum) printf("Yes\n");109else printf("No\n");110 }111return0;112 }据说这是典型的最⼤流题⽬,然⽽为了强⾏安利⼀波⼆分图的多重匹配,就不说成那个了。
二分图匹配(匈牙利算法)

设G=(V,{R})是一个无向图。
如顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属两个不同的子集。
则称图G为二分图。
v给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配。
v选择这样的边数最大的子集称为图的最大匹配问题(maximal matching problem)v如果一个匹配中,图中的每个顶点都和图中某条边相关联,则称此匹配为完全匹配,也称作完备匹配。
最大匹配在实际中有广泛的用处,求最大匹配的一种显而易见的算法是:先找出全部匹配,然后保留匹配数最多的。
但是这个算法的复杂度为边数的指数级函数。
因此,需要寻求一种更加高效的算法。
匈牙利算法是求解最大匹配的有效算法,该算法用到了增广路的定义(也称增广轨或交错轨):若P是图G中一条连通两个未匹配顶点的路径,并且属M的边和不属M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M 的一条增广路径。
由增广路径的定义可以推出下述三个结论:v 1. P的路径长度必定为奇数,第一条边和最后一条边都不属于M。
v 2. P经过取反操作(即非M中的边变为M中的边,原来M中的边去掉)可以得到一个更大的匹配M’。
v 3. M为G的最大匹配当且仅当不存在相对于M的增广路径。
从而可以得到求解最大匹配的匈牙利算法:v(1)置M为空v(2)找出一条增广路径P,通过取反操作获得更大的匹配M’代替Mv(3)重复(2)操作直到找不出增广路径为止根据该算法,我选用dfs (深度优先搜索)实现。
程序清单如下:int match[i] //存储集合m中的节点i在集合n中的匹配节点,初值为-1。
int n,m,match[100]; //二分图的两个集合分别含有n和m个元素。
bool visit[100],map[100][100]; //map存储邻接矩阵。
bool dfs(int k){int t;for(int i = 0; i < m; i++)if(map[k][i] && !visit[i]){visit[i] = true;t = match[i];match[i] = k; //路径取反操作。
二分图

匈牙利算法和KM算法简介
二分图的概念
二分图又称作二部图,是图论中的一种特殊 模型。 设G=(V,{R})是一个无向图。如顶点集V可分 割为两个互不相交的子集,并且图中每条边 依附的两个顶点都分属两个不同的子集。则 1 2 3 4 5 称图G为二分图。
1
2
3
4
最大匹配
给定一个二分图G,在G的一个子图M中,M 的边集{E}中的任意两条边都不依附于同一个 顶点,则称M是一个匹配。 选择这样的边数最大的子集称为图的最大匹 最大匹 配问题(maximal matching problem) 配问题 如果一个匹配中,图中的每个顶点都和图中 某条边相关联,则称此匹配为完全匹配 完全匹配,也 完全匹配 称作完备匹配。 完备匹配。 完备匹配
KM算法
穷举的效率-n!,我们需要更加优秀的算法。 定理: 设M是一个带权完全二分图G的一个完备匹配,给 每个顶点一个可行顶标(第i个x顶点的可行标用lx[i] 表示,第j个y顶点的可行标用ly[j]表示),如果对所 有的边(i,j) in G,都有lx[i]+ly[j]>=w[i,j]成立(w[i,j]表示 边的权),且对所有的边(i,j) in M,都有lx[i]+ly[j]=w[i,j] 成立,则M是图G的一个最佳匹配。证明很容易。
匈牙利算法
在主程序中调用下面的程序即可得出最大匹 配数。 Bmatch := 0; For I:=1 to n do Bmatch := Bmatch + find(i); Writeln(Bmatch); 一个关于二分图的性质: 最大匹配数+最大独立集=X+Y
最佳匹配
如果边上带权的话,找出权和最大的匹配叫 做求最佳匹配。 实际模型:某公司有职员x1,x2,…,xn,他们去 做工作y1,y2,…,yn,每个职员做各项工作的效 益未必一致,需要制定一个分工方案,使得 人尽其才,让公司获得的总效益最大。 数学模型:G是加权完全二分图,求总权值 最大的完备匹配。
数学建模-图论

图论导引
问题3:四色猜想 地图或地球仪上,最多用四种颜色就可把每一 国的版图染好,使得国界线两侧异色。
电子计算机问世以后,由于演算速度迅速提高,加 之人机对话的出现,大大加快了对四色猜想证明的进 程。美国伊利诺大学哈肯在1970年着手改进“放电过 程”,后与阿佩尔合作编制一个很好的程序。就在 1976年6月,他们在美国伊利诺斯大学的两台不同的电 子计算机上,用了1200个小时,作了100亿判断,终于 完成了四色定理的证明,轰动了世界。
有向图:
1, 若vi是ei的始点 aij 1, 若vi是ei的终点 0, 若v 与e 不关联 i i
无向图:
1, 若vi与v j 关联 aij 0, 若vi与v j 不关联
图的矩阵表示
例6:写出右图与其基本图 的关联矩阵 解:分别为:
图论的基本概念
几个基本定理:
1、对图G V,E ,有 d v 2 E .
vV
2、度为奇数的顶点有偶数个。
3、设G V,E 是有向图, 则 d v d v E .
vV vV
子图
定义 设图 G=(V,E, ),G1=(V1,E1, 1 )
(3)设 E1 E,且 E1 ,以 E1 为边集,E1 的端点集为顶点集的图 G 的子图, 称为 G 的由 E1 导出的子图,记为 G[E1].
G
G[{v1,v4,v5}]
G[{e1,e2,e3}]
基 本 概 念
定义1 在无向图 G=(V,E)中: (1) 顶点与边相互交错的有限非空序列 w (v0 e1v1e2 vk 1ek vk ) 称为一条从 v 0 到 v k 的通路,记为 Wv0vk (2)边不重复但顶点可重复的通路称为道路,记为 Tv0vk (3)边与顶点均不重复的通路称为路径,记为 Pv 0 v k 始点和终点相同的路称为圈或回路.
数学建模图论模型

任意两点均有通路的图称为连通图。
连通而无圈的图称为树,常用T=<V,E>表示树。
若图G’是图 G 的生成子图,且G’又是一棵树, 则称G’是图G 的生成树。
例 Ramsey问题
图1
图2
并且常记: V = v1, v2, … , vn, |V | = n ; E = {e1, e2, … , em}ek=vivj , |E | = m
称点vi , vj为边vivj的端点 在有向图中, 称点vi , vj分别为边vivj的 始点和终点. 该图称为n,m图
8
对于一个图G = V, E , 人们常用图形来表示它, 称其 为图解 凡是有向边, 在图解上都用箭头标明其方向.
4、P'代替P,T'代替T,重复步骤2,3
定理2 设 T为V的子集,P=V-T,设 (1)对P中的任一点p,存在一条从a到p的最短路径,这条路径仅有P中的
点构成, (2)对于每一点t,它关于P的指标为l(t),令x为最小指标所在的点, 即:
l(x)mli(tn )} t{ ,T
(3)令P’=P Ux,T’=T-{x},l’(t)表示T'中结点t关于P'的指标,则
解:用四维01向量表示人,狼,羊,菜例在过河西河岸问的题状态(在
岸则分量取1;否则取0),共有24 =16 种状态; 在河东岸 态类似记作。
由题设,状态(0,1,1,0),(0,0,1,1),(0,1,1,1)是不允许的
其对应状态:(1,0,0,1), (1,1,0,0),(1,0,0,0)也是不允许
程序设计竞赛常用算法

程序设计竞赛常用算法1.排序算法:排序是一个基本的算法问题,常见的排序算法有冒泡排序、选择排序、插入排序、快速排序、归并排序等。
这些排序算法有各自的优势和适用场景,需要根据具体问题需求选择合适的算法。
2.图论算法:图论是程序设计竞赛中经常出现的重要领域。
常见的图论算法有深度优先(DFS)、广度优先(BFS)、Dijkstra算法、Floyd-Warshall算法、拓扑排序、最小生成树等。
这些算法可以用于解决最短路径、连通性、最大流最小割等问题。
3.动态规划:动态规划是一种常用于解决优化问题的算法。
该算法通过将问题分解成子问题,并记录子问题的解来求解原问题的最优解。
常见的动态规划算法有背包问题、最长公共子序列(LCS)、最大子序列和等。
4.字符串处理算法:字符串处理是程序设计竞赛中常见的问题。
常见的字符串处理算法有KMP算法、哈希算法、字符串匹配等。
这些算法可以用于解决模式匹配、字符串、字符统计等问题。
5.数学算法:数学算法在程序设计竞赛中也经常被使用。
常见的数学算法有质因数分解、素数筛、快速乘法、高精度计算等。
这些算法可以用于解决数论、计算几何、概率等问题。
6.图形算法:图形算法主要用于处理图像和几何图形。
常见的图形算法有扫描线算法、凸包算法、几何运算等。
这些算法可以用于解决图像处理、三维建模等问题。
7.树和图的遍历算法:树和图的遍历算法是程序设计竞赛中常用的算法之一、常见的树和图的遍历算法有先序遍历、中序遍历、后序遍历、深度优先(DFS)、广度优先(BFS)等。
这些算法可以用于解决树和图的构建、路径等问题。
8.最大匹配和最小割算法:最大匹配算法用于求解二分图的最大匹配问题,常见的算法有匈牙利算法。
最小割算法用于求解图的最小割问题,常见的算法有Ford-Fulkerson算法。
这些算法可以用于解决网络流和二分图匹配等问题。
9.贪心算法:贪心算法是一种常用于优化问题的算法。
该算法通过每一步选择局部最优解来达到全局最优解。
利用匈牙利算法求完美匹配例题

一、概述匈牙利算法是一种用于求解二分图最大匹配的经典算法,它的时间复杂度为O(n^3),在实际应用中具有广泛的用途。
本文将通过一个具体的例题,详细介绍利用匈牙利算法求解完美匹配的具体步骤和方法。
二、问题描述假设有一个二分图G=(V, E),其中V={U,V},U={u1,u2,u3},V={v1,v2,v3},E={(u1,v1),(u1,v2),(u2,v2),(u3,v3)},现在希望求解这个二分图的最大匹配。
三、匈牙利算法详解1. 初始化:需要初始化一个大小为|U|的数组match[],用来记录每一个U中的顶点匹配的V中的顶点,初始化为-1,表示初始时没有匹配的顶点。
2. 寻找增广路径:通过遍历U中的每一个顶点,逐个寻找增广路径。
对于每一个未匹配的顶点,都尝试进行增广路径的寻找。
3. 匹配顶点:如果找到了一条增广路径,将增广路径上的顶点逐个匹配,并更新match[]数组。
4. 寻找最大匹配:重复上述步骤,直至无法继续寻找增广路径为止,此时match[]数组中记录的就是二分图的最大匹配。
四、具体例题求解接下来通过一个具体的例题来详细介绍匈牙利算法的求解过程。
假设有一个二分图G=(V, E),其中V={U,V},U={u1,u2,u3},V={v1,v2,v3},E={(u1,v1),(u1,v2),(u2,v2),(u3,v3)}。
首先初始化match[]数组为{-1,-1,-1}。
(1)对u1进行增广路径的寻找由于u1未匹配,从u1开始寻找增广路径。
首先考虑与u1相连的v1和v2。
对v1进行匹配,得到match[0]为1。
对v2进行匹配,得到match[0]为1。
(2)对u2进行增广路径的寻找由于u2未匹配,从u2开始寻找增广路径。
考虑与u2相连的v2。
对v2进行匹配,得到match[1]为2。
(3)对u3进行增广路径的寻找由于u3未匹配,从u3开始寻找增广路径。
考虑与u3相连的v3。
对v3进行匹配,得到match[2]为3。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Empty Grass Wall
墙
空地 Empty
草地
Grass Wall
墙
【模型一】 在问题的原型中,草地,墙这些信息不是我们 所关心的,我们关心的只是空地和空地之间的联系。 因此,我们很自然想到了下面这种简单的模型: 以空地为顶点,有冲突的空地间连边,我们可 以得到右边的这个图 :
例题1 NOIP2010,第三题 关押罪犯
将N个人分成两组,其中M对人有Ci的不 和谐值,如果有不和谐值为Ci的两人在 同一组,那么就会有Ci的不和谐值。 要求找出一个分组方案,使得最大不和 谐值最小。 N<=20000 M<=100000
例题解答
直接做不好下手 由于要求最大值最小,即一个上界,所 以我们可以二分这个上界 那么我们就能确定哪些人不能在一组(不 和谐值大于上界的) 我们新建一张图,把不能在一组的人之 间连边,此时我们只需判断这个图能否 构成二分图即可。 复杂度O(MlogM),实现简单
残量网络与增广轨
残量网络G’=(V,E,C),其中V,E与原网络G 相同,C为G中的容量-当前流量(即剩余 可流量) 增广轨就是一条S-T的不包含可流量为0 的边的路径 许多最大流算法都是通过不断找增广轨 进行增广从而得到最大流 定理:当前流为最大流当且仅当无增广 轨
一个重要的问题
增广一次,增加1的流量后无增广轨了,而最大流却不是 1. 我们可以走1-2-4和1-3-4得到2的流量
完全匹配
匹配边的端点为所有图中顶点
二分图的判定
判定一个无向图能否构成二分图 算法:BFS,复杂度O(M) 我们从任一点开始,令其在二分图左边 ,然后开始BFS,每次搜到的点放对面即 可,直至所有点放完或出现矛盾 正确性: 对于每个连通量而言,一个点如果确定 ,其他点均确定,而这个点放左,放右 实际上是对称的方案
最大流流量=最小割容量
引理:对于任一可行流F和任一割K,均有
当所有割边满流时等号 设F*为最大流,P*为最小割 我们找到一个割集P
aK aK
F (S ) F ( K ) C ( K ) Cap( K )
由引理得 F * ( S ) Cap( P*) ( P, P)之间的边必然满流 对于 且由割与最小割的关系 F * (S ) Cap( P) Cap( P*) 所以 F * (S ) Cap( P*)
Hopcroft-Karp算法
借用Dinic分层思想 每次对二分图分层(把二分图看做网络) 再用匈牙利算法,但是每次只走 a标号+1=b标号的边 可以证明最多进行 N 次分层 每次用O(M)的时间找增广轨 复杂度 O( N * M ) 目前已知的最快二分图匹配算法
小结
时间复杂度 网络流算法 匈牙利算法 Hopcroft-Karp 算法 O(N2*M) O(N*M) O(N0.5*M) 代码长度 较长 短 中等 思维难度 较低 低 中等
例题解答
但是O(M^2)的判断太慢 考虑到平面图的性质:边数与点数同阶 (在本题中可以3*N-6条边作为上限,如 果超过则直接判非平面图) 所以复杂度为O(N^2*T)
网络流
现在想将一些物资从S运抵T,必须经过一些中转站。 连接中转站的是公路,每条公路都有最大运载量。 每条弧代表一条公路,弧上的数表示该公路的最大运 载量。最多能将多少货物从S运抵T? V1 V3 4 7 4 1 2 S 4 6 T
平面图的判定不好做 考虑问题特殊性 1,每条边其实有 两种画法,在里面 或在外面 2,每条边在里面或 外面可能会与其他边在里面或外面矛盾 (如蓝色与绿色矛盾)
例题解答
我们把每条边在里面,在外面这两种选 择看成两个点,那么一共有2M个点 用O(M^2)的时间判断每两个点是否矛盾 如果矛盾就连条边(保证自己选了,则矛 盾的都不选,或自己不选,矛盾的必选) 我们把每条边在里面与在外面连条边 (保证两个选择只选一个) 那么如果这个图能构成二分图,则原问
1
1
2 3 4 5
水平方向的块编号 竖直方向的块编号
3 4
2
把每个横向块看作X部的点,竖向块看作Y部的点,若 两个块有公共的空地,则在它们之间连边。于是,问题转 化成这样的一个二分图:
由于每条边表示一个空地,有冲突的空地之间必有 公共顶点,所以问题转化为二分图的最大匹配问题。
例
赛车问题
问题描述
问题的求解目标是寻求图G的最大独立集,即求G的 独立数α (G)。一般图的α (G)是很难计算的。 独立集是原图点集的一个子集,其中任意两点之间 没有边。 显然这一模型不是属于一些特殊的图,给我们设计 算法带来很大的麻烦。
【模型二】
我们将每一行,每一列被墙隔开,且包含空地的连续区域称 作“块”。显然,在一个块之中,最多只能放一个机器人。我 们把水平方向的这些块编上号;同样,把竖直方向的块也编上 号。
S2这个源点与S2S这条弧都可以不要,只需规定最多扩展M次流量即可
则称之为网络流图,记为G = (V,E,C)
可行流
对于网络流图G,每一条弧(i,j)都给定一个非负数fij,这一组 数满足下列三条件时称为这网络的可行流,用f表示它。 1. 流量限制 每一条弧(i,j)有fij≤Cij 2. 流量平衡 除源点S和汇点T以外的所有的点vi,恒有: ∑j(fij)= ∑k(fjk) 该等式说明中间点vi的流量守恒,输入与输出量相等。 3. 对于源点S和汇点T有 , ∑i(fSi)= ∑j(fjT)= V(f) 该等式说明源点流出量等于汇点流入量等于网络流流量
B[j]:=true L[j]为0或者Find(L[j])为真 //L数组记录右边每点匹配的左边点
L[j]:=I ,find:=true,exit; //找到就退出,返回真
Find:=false; //没找到 End Function 主程序 For I:=1~N
Fillchar(B,0,sizeof(B)) If find(i) then inc(Ans);
阿 P与阿Q都是四驱车好手,他们各有N辆四驱车。为了一比高下,他 们约好进行一场比赛。
这次比赛共有M个分站赛,赢得分站赛场次多的获得总冠军。
每个分站赛中,两人各选一辆自己的赛车比赛。分站赛的胜负大部分 取决于两车的性能,但由于种种原因(如相互之间的干扰),性能并不 是决定胜负的唯一指标,有时会出现A赢B、B赢C、C赢D、D又赢A的局 面。幸好有一种高智能机器,只要给定两辆四驱车,就能立刻判断谁会 赢,在总比赛前它就已经把阿 p的每辆车与阿q的每辆车都两两测试过了, 并且还把输赢表输入了电脑。 另外,由于比赛的磨损,每辆四驱车都有自己的寿命(即它们能参加 分站赛的场次),不同的四驱车寿命可能不同,但最多不会超过 50场。 两辆四驱车最多只能交手一次。 现给定N、M(1<=N<=100,1<=M<=1000)、N*N的一个输赢 表、每辆四驱车的寿命,并假设每次分站赛两人都有可选的赛车,请你 计算一下阿P最多能够赢得多少个分站赛。
由于匈牙利算法简单好写,并且实际表现非常优秀,所 以推荐优先选择匈牙利算法。
例题 机器人布阵
有一个N*M(N,M<=50)的棋盘,棋盘的每一格是三种类型 之一:空地、草地、墙。机器人只能放在空地上。在同 一行或同一列的两个机器人,若它们之间没有墙,则它 们可以互相攻击。问给定的棋盘,最多可以放置多少个 机器人,使它们不能互相攻击。
构
图
1、建立N个点代表阿P的N辆车,分别以1到N标号; 2、建立N个点代表阿Q的N辆车,分别以N+1到2N标号;
3、如果阿P的第I辆车能够跑赢阿Q的第J辆车,则加一条弧IN+J, 容量为1,表示两辆四驱车最多只能交手一次; 4、增加一个源点S,S与 1到N中的每一个结点I都连一条弧SI, 容量为阿P的第I辆车的寿命;
复杂度为O(N^2*M)
二分图的最大匹配
算法一:网络流 算法二:匈牙利算法 算法三:Hopcroft-Karp算法
网络流算法解二分图最大匹配
对于二分图G 新建源点S,汇点T S连向左边所有点,容量为1 原图所有边容量为1 右边所有点连向T,容量为1 对此网络求最大流,最大流流量即为最 大匹配数。
反向弧
刚才产生的问题在于没有“后悔”的机 会 怎么解决? 回溯搜索?复杂度上升至指数级。 我们给每条边增加一条反向弧 即对于(i,j,c)我们增加边(j,i,0) 当(i,j,c)被增广了X的流量后,我们把反 向弧的可流量增加X
割切
将所有点划分为两个点集。 其中S和T在不同点集 割的容量为两点集之间的边的容量和 右图割容量: 8+4+4+1 =17
例题2 HNOI 2010 Planar
给定一个图,此图有一个包含所有顶点 的环(可以认为1-2-3-..-N-1) 判断此图是否为平面图 平面图
若能将无向图G画在平面上,使得任意两条 边不相交(可以在端点重合),则为平面图
T组数据 T<=100 N<=200 M<=10000
例题解答
匈牙利算法
依然是找增广轨的思想 循环每个左边点
以此点为起点找增广轨 如果找到则增广
循环N个点,每次找增广轨最多要找M次 复杂度O(Nion Find(i):boolean 循环每个i邻接的点j