二分图最大匹配初探 By cellur925

一、什么是二分图

首先它需要是一张无向图。

之后它需要同时满足两个条件:①它的N个点被分为两个集合,且这两个集合交集为空;②同一集合内的点之间没有边相连。

二、无向图是否为二分图的判定

引理:无向图是二分图当且仅当图中不存在为奇环。(证明不会略)

方法:基于染色法。如把当前点染为黑色,尝试把与它相邻的点染成白色。若发现和他相邻的点已被染色还不是白色,证明存在奇环,则不是二分图

实现:可用BFS,也可用DFS,复杂度O(N+M)。

 1 bool check(int w)
 2 {
 3     memset(vis,0,sizeof(vis));
 4     queue<int>q;
 5     for(int k=1;k<=n;k++)
 6         if(!vis[k])
 7         {
 8             q.push(k);vis[k]=1;
 9             while(!q.empty())
10                 {
11                     int x=q.front();
12                     q.pop();
13                     for(int i=head[x];i;i=edge[i].next)
14                     if(edge[i].val>=w)
15                     {
16                         int y=edge[i].to;
17                         if(!vis[y]) vis[y]=3-vis[x],q.push(y);
18                         else if(vis[y]==vis[x]) return false;
19                         }
20                 }
21         }
22     return true;
23 }

例题:关押罪犯(丢链接跑)

三、二分图最大匹配

*一些概念:

  图的一组匹配:边集。满足“任意两条边都没有公共端点”。

  最大匹配:含边数最多的一组匹配。

匹配算法:匈牙利算法(增广路算法/搞对象算法)

(注:增广路这部分不是很懂qwq,鉴于学长的建议等,就先把算法的实现记下了qwq,如果我能苟到省选就再学一遍qwq)

 1 bool dfs(int x)
 2 {
 3     for(int i=head[x];i;i=edge[i].next)
 4     {
 5         int y=edge[i].to;
 6         if(!vis[y])
 7         {
 8             vis[y]=1;
 9             if(!match[y]||dfs(match[y]))
10             {
11                 match[y]=x;
12                 return 1;
13             }
14         }
15     }
16     return 0;
17 }

主程序

1     for(int i=1;i<=n;i++)
2     {
3         memset(vis,0,sizeof(vis));
4         if(dfs(i)) ans++;
5     }

例题1 完美的牛栏 最大匹配裸题

例题2 [ZJOI2009]假期的宿舍   题解链接

猜你喜欢

转载自www.cnblogs.com/nopartyfoucaodong/p/9695860.html