二分图定义:可以把图分成两块 两块图之间没有边相连
当且仅当图中不含有奇数环才会有二分图 反之 二分图一定没有奇数环
染色法
用深搜和宽搜都可以
#include<iostream>
#include<cstring>
using namespace std;
int n,m;
const int N=1e5+10,M=2*N;
int h[N],ne[M],e[M],idx;
int color[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool dfs(int u,int c)
{
color[u]=c;//给u染色
for(int i=h[u];i!=-1;i=ne[i])//遍历与u相邻的点
{
int j=e[i];
if(!color[j])
{
if(!dfs(j,3-c))//如果c是1 下面就染2色
return false;
}
else if(color[j]==c)//如果该点染过颜色并且这个颜色和u点相同 说明这不是二分图
return false;
}
return true;
}
int main()
{
cin>>n>>m;
memset(h,-1,sizeof h);
while(m--)
{
int a,b;
cin>>a>>b;
add(a,b),add(b,a);
}
bool flag=true;
for(int i=1;i<=n;++i)
{
if(!color[i])//如果没有染过颜色
{
if(!dfs(i,1))//给它染1色 如果返回false
{
flag=false;
break;
}
}
}
if(flag)
puts("Yes");
else
puts("No");
}
匈牙利算法
..不知道该怎么描述这个算法
这个算法是求二分图中的最大匹配数
#include<iostream>
#include<cstring>
using namespace std;
const int N=510,M=100010;
int n1,n2,m;
int h[N],e[M],ne[M],idx;
bool st[N];//每一轮的临时预定数组 标记当前循环该女孩有没有被预定
int match[N];//表示女孩现有配对男友
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool findd(int x)//判断前面匹配成功的人能不能换女朋友
{
for(int i=h[x];i!=-1;i=ne[i])//遍历自己喜欢的女孩
{
int j=e[i];
if(!st[j])//如果在这一轮模拟匹配中 这个女孩尚未被预定
{
st[j]=true;//那x就预定女孩j
if(!match[j]||findd(match[j]))//如果女孩j没有男朋友或者她原来的男朋友能预定其他喜欢的女孩 配对成功
{
match[j]=x;
return true;
}
}
}
return false;//自己中意的全部都被预定了 配对失败。
}
int main()
{
int n1,n2,m;
cin>>n1>>n2>>m;
memset(h,-1,sizeof h);
while(m--)
{
int a,b;
cin>>a>>b;
add(a,b);
}
int ans=0;//记录最大匹配数
for(int i=1;i<=n1;++i)
{
memset(st,false,sizeof st);//因为每次模拟匹配的预定情况都是不一样的 所以每轮模拟都要初始化
if(findd(i))
ans++;
}
cout<<ans<<endl;
}