题干:

There are a group of students. Some of them may know each other, while others don't. For example, A and B know each other, B and C know each other. But this may not imply that A and C know each other. 

Now you are given all pairs of students who know each other. Your task is to divide the students into two groups so that any two students in the same group don't know each other.If this goal can be achieved, then arrange them into double rooms. Remember, only paris appearing in the previous given set can live in the same room, which means only known students can live in the same room. 

Calculate the maximum number of pairs that can be arranged into these double rooms. 

Input

For each data set: 
The first line gives two integers, n and m(1<n<=200), indicating there are n students and m pairs of students who know each other. The next m lines give such pairs. 

Proceed to the end of file. 
 

Output

If these students cannot be divided into two groups, print "No". Otherwise, print the maximum number of pairs that can be arranged in those rooms. 

Sample Input

4 4
1 2
1 3
1 4
2 3
6 5
1 2
1 3
1 4
2 5
3 6

Sample Output

No
3

题目大意:

有n个学生。其中有些人相互认识,有些人相互之间不认识。现在有m对认识关系。问你能否把这n个人分成两个组。一个组中没有相互认识的人。如果不能做到的话,输出NO。如果可以的话,把这些人分到一些房间中,只有相互认识的人能分到一个房间里。问你需要多少房间。
 

解题报告:

   这是判断二分图和二分图匹配的裸题。

首先要判断该图是否为二分图。当该图为二分图时,才能分为两个组。当判断为二分图时,我们需要求出该二分图的最大匹配数目。得出的结果除2就得出了需要房间数。(或者只对col==1的进行find匹配,这样就不需要除以2了。)

二分图的判定:
    在判定一个图是否为二分图的时候只需要进行判断图中是否存在奇数长度的回路
    常用的办法是基于BFS的相邻染色法 即对任意一个点进行BFS如果uv之间有一条边 我们从u访问到v 如果v未被染色 则v将被染成和u相对的染色(比如1和0)
   判断出口:如果相邻节点(u和v)是相同颜色 则存在奇回路

   还有个优化(但是貌似没卵用),就是used数组不是bool的,设成int,然后每次就不需要置零used了,直接看是否等于i就可以了,相当于find中两个参数find(i,i),其中bool find(int x,int id),看是否是id,就可以看出是否是

AC代码:

#include<bits/stdc++.h>
using namespace std;
int nxt[205];
int col[205];
bool used[205];
int n,m;
vector<int> vv[205];
bool bfs() {
	memset(col,-1,sizeof col);
	queue<int> q;
	q.push(1);col[1] = 1;
	while(!q.empty()) {
		int cur = q.front();q.pop();
		for(int i = 0; i<vv[cur].size(); i++) {
			int now = vv[cur][i];
			if(col[now] == -1) {
				col[now] = !col[cur];
				q.push(now);
			}
			else {
				if(col[now] == col[cur]) return 0;
			}
		}
	} 
	return 1;
}
bool find(int x) {
	for(int i = 0; i<vv[x].size(); i++) {
		int now = vv[x][i];
		if(used[now] == 1) continue;
		used[now] = 1;
		if(nxt[now] == 0 || find(nxt[now])) {
			nxt[now] = x;
			return 1;
		}
	}
	return 0 ;
}
int main()
{
	int u,v,ans;
	while(~scanf("%d%d",&n,&m)) {
		memset(nxt,0,sizeof nxt);
		for(int i = 0; i<=200; i++) vv[i].clear();
		for(int i = 1; i<=m; i++) {
			scanf("%d%d",&u,&v);
			vv[u].push_back(v);
			vv[v].push_back(u);
		}
		if(!bfs()) {
			puts("No");continue;
		}
		ans = 0;
		for(int i = 1; i<=n; i++) {
			memset(used,0,sizeof used);
			if(find(i)) ans++;
		}
		printf("%d\n",ans/2);
	}
	
	return 0;
}

总结:

   1WA了,因为忘记了清空vv和nxt数组。