二分图的判断以及二分图的最大匹配
题意:给定n个学生,他们之间可能互相认识,首先判断能不能将这些学生分为两组,使组内学生不认识;
现想将学生两两分组,且保证每一组的学生都认识,这样分组可达到的最大组数为多大?
首先,利用交叉染色法判断一个图是否为二分图。。。
用DFS就可;取任意点,标记,搜索与其有边的点,如果该点没有被标记,则将其标记为相反,继续向下搜索;如果被标记了,则判断其标记与应该被标记的值是否一致,一致则继续,不一致则判断该图不是二分图。
然后,则是二分图的最大匹配的计算;
建立一张二分图,左右两边都是图的所有节点;
取左端节点,依次向下判断是否在右端存在节点与其相连;
每次判断时,如果节点的右端相连的节点已经存在左端的节点与之相连,则判断该左端节点是否还有另外的节点可以与之相连,依次递归的向下推;
代码:
#include<iostream>
#include<vector>
using namespace std;
vector <int> ver[1000];
int exist[1000];
int havever[1000];
int flag[1000];
int n,m;
int DFS(int start,int cer){
for(int i=ver[start].size()-1;i>=0;i--){
if(!flag[ver[start][i]]){
flag[ver[start][i]]=-cer;
if(!DFS(ver[start][i],-cer))
return false;
}
else{
if(flag[ver[start][i]]==cer){
return false;
}
}
}
return true;
}
bool ishalf(){
memset(flag,0,sizeof(flag));
flag[1]=1;
if(DFS(1,1))
return true;
return false;
}
bool able(int start){
for(int k=ver[start].size()-1;k>=0;k--){
int temp=ver[start][k];
if(exist[temp]==-1){
exist[temp]=1;
if(havever[temp]==-1||able(havever[temp])){
havever[temp]=start;
return true;
}
}
}
return false;
}
int find(){
int sum=0;
memset(havever,-1,sizeof(havever));
for(int j=1;j<=n;j++){
memset(exist,-1,sizeof(exist));
if(able(j))
sum++;
}
return sum;
}
int main(){
// int n,m;
while(cin>>n>>m){
for(int i=0;i<=n;i++){
ver[i].clear();
}
for(int i=0;i<m;i++){
int temp1,temp2;
cin>>temp1>>temp2;
ver[temp1].push_back(temp2);
ver[temp2].push_back(temp1);
}
bool res=ishalf();
if(!res){
cout<<"No"<<endl;
continue;
}
int times=find();
cout<<times/2<<endl;
}
return 0;
}