二分图

二分图:

如果一个图中的所有顶点可以分成左右两个集合,两个集合不存在任意两个顶点是直接相连的。

也就是说:同一个点集中任意两个点之间没有边,一条边上的两个顶点一定不在同一个集合。

染色法判断二分图:

给每个点设置一个标志,如果一个点标记为1,那么它的直接后继节点为2,如果一个点被标记两次不同的值,那么说明图中存在奇数边的环,该图不是二分图。

二分图当且仅当图中不存在奇数边环;二分图可以是不连通的。

代码思路:

依次对每个点进行染色,直接对图dfs一遍,如果一个点被染了两次就结束,说明该图不是二分图,如果所有点都被成功染色,说明该图是二分图。

复制代码
 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 const int N=1e5+10,M=200010;
 5 int h[N],e[M],ne[M],idx;
 6 int colore[N];
 7 int m,n;
 8 void add(int a,int b)
 9 {
10     e[idx]=b;ne[idx]=h[a];h[a]=idx++;
11 }
12 bool dfs(int u,int c)
13 {
14     colore[u]=c;
15     for(int i=h[u];i!=-1;i=ne[i])
16     {
17         int j=e[i];
18         if(!colore[j])
19         {
20             if(!dfs(j,3-c)) return false;
21         }
22         else if(colore[j]==c) return false;
23     }
24     return true;
25 }
26 int main()
27 {
28     cin>>n>>m;
29     memset(h,-1,sizeof h);
30     while(m--)
31     {
32         int u,v;
33         cin>>u>>v;
34         add(u,v);add(v,u);
35     }
36     bool flag=true;
37     for(int i=1;i<=n;i++)
38     {
39         if(!colore[i])
40         {
41             if(!dfs(i,1)) 
42             {
43                 flag=false;
44                 break;
45             }
46         }
47     }
48     if(flag) puts("Yes");
49     else puts("No");
50     return 0;
51 }
View Code
复制代码

匈牙利算法:

适用于求二分图的最大匹配数;

最大匹配数:求二分图两个点集之间一共有多少直接相连的两两成对的点对。一对一关系。

 

复制代码
 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 const int N=510,M=100010;
 5 int h[N],e[M],ne[M],idx;
 6 int n1,n2,m;
 7 int match[N];
 8 bool st[N];
 9 void add(int a,int b)
10 {
11     e[idx]=b;ne[idx]=h[a];h[a]=idx++;
12 }
13 bool find(int x)
14 {
15     for(int i=h[x];i!=-1;i=ne[i])
16     {
17         int j=e[i];
18         if(!st[j])
19         {
20             st[j]=true;
21             if(match[j]==0||find(match[j]))
22             {
23                 match[j]=x;
24                 return true;
25             }
26         }
27     }
28     return false;
29 }
30 int main()
31 {
32     cin>>n1>>n2>>m;
33     memset(h,-1,sizeof h);
34     while(m--)
35     {
36         int u,v;
37         cin>>u>>v;
38         add(u,v);
39     }
40     int res=0;
41     for(int i=1;i<=n1;i++)
42     {
43         memset(st,false,sizeof st);
44         if(find(i)) res++;
45     }
46     cout<<res<<endl;
47     return 0;
48 }
View Code
复制代码

 

posted @   Mrr-  阅读(58)  评论(1编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程
点击右上角即可分享
微信分享提示