题意:
一群人,有的两人之间认识,有的不认识,认识关系不存在传递性(A 认识 B,B 认识 C ≠ A 认识 C )
给定哪几个人相互认识,问是否能把这群人分成两组,使得不同组的人之间两两都不认识。
如果可行,安排两个认识的人一组住一个房间,问最多能有多少组人能住同一个房间。
分析:
第一步,判断能否分成两组,即判定所给图是否是二分图,
染色法:选定一个起点,把该点染成黑色,以该点开始进行dfs,
搜到相邻的点,如果该点没染过色,则把该点染成与它的前驱节点相反的颜色,
如果搜到一个节点与它的前驱节点颜色相同,则说明不是二分图。
第二步,求最大匹配直接用匈牙利算法
Source Code:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 200 + 10;
int n, m;
int nextpt[maxn];
int mp[maxn][maxn];
int color[maxn];
bool vis[maxn];
bool flag;
void judge( int x, int cr )
{
if( flag == false )
return;
for( int i = 1; i <= n; i++ )
{
if( mp[x][i] )
{
if( !color[i] )
{
color[i] = -cr;
judge( i, color[i] );
}
else if( color[i] == cr )
{
flag = false;
return;
}
}
}
}
bool isBipGraph()
{
flag = true;
color[1] = 1;
judge( 1, 1 );
return flag;
}
bool dfs( int s )
{
for( int i = 1; i <= n; i++ )
{
if( !vis[i] && mp[s][i] != 0 )
{
vis[i] = 1;
if( nextpt[i] == -1 || dfs( nextpt[i] ) )
{
nextpt[i] = s;
return true;
}
}
}
return false;
}
void init()
{
memset( color, 0, sizeof( color ) );
memset( mp, 0, sizeof( mp ) );
memset( nextpt, -1, sizeof( nextpt ) );
}
int main()
{
int x, y;
while( ~scanf( "%d%d", &n, &m ) )
{
init();
for( int i = 1; i <= m; i++ )
{
scanf( "%d%d", &x, &y );
mp[x][y] = 1;
}
if( isBipGraph() )
{
int ans = 0;
for( int i = 1; i <= n; i++ )
{
memset( vis, 0, sizeof( vis ) );
if( dfs( i ) )
ans++;
}
printf( "%d\n", ans );
}
else
printf( "No\n" );
}
return 0;
}