B - The Accomodation of Students
题目的意思就是,有好多好多的学生,他们部分相互认识,有些就不认识。但若A认识B,B认识C ,A是不一定认识C的。
问是否能划分为二分图,可以的话求出最大匹配。
脑洞:让我判断,那我就bfs染色呗。但要注意一个地方,二分图可能是分裂的,即他的某个部分和某个部分不一定有连接的边。还是太菜了,这里wr了两发- -。
然后其他的就都是模板了。
int n, m;
int vis[len], l[len], x[len], y[len];
int w[len][len];
int clr[len];
int num_x, num_y;
queue <int> q;//bfs用的queue
int main(){
while (cin >> n >> m) {
Init();
for (int i=0; i<m; i++){
int s,t;
cin >> s >> t;
w[s][t] ++; w[t][s] ++;
}//读图
bool flag = false;
for(int i=1; i<=n; i++)//每个点都要看一次,以免分开的情况{
if(clr[i] == -1 && !bfs(i)){
flag = true;
break;
}
}
if (flag){
cout << "No" << endl;
continue;
}
for (int i=1; i<=n; i++){
if (clr[i] == 1) x[num_x++] = i;
if (clr[i] == 0) y[num_y++] = i;
}
// for (int i=1; i<=n; i++) cout << clr[i] << " ";
// cout << endl;
// for (int i=1; i<=num_x-1; i++) cout << x[i] << " ";
// cout << endl;
// for (int i=1; i<=num_y-1; i++) cout << y[i] << " ";
// cout << endl;
int ans = 0;
for (int i=1; i<=num_x-1; i++){
memset(vis, 0, sizeof(vis));
if (find(x[i])) ans++;
}
// for (int i=1; i<=n; i++)
// cout << l[i] << " ";
// cout << endl;
cout << ans << endl;
}
return 0;
}
void Init(){
memset(vis, 0, sizeof(vis));
memset(l, 0, sizeof(l));
memset(x, 0, sizeof(x));
memset(y, 0, sizeof(y));
memset(w, 0, sizeof(w));
memset(clr, -1, sizeof(clr));
num_x = num_y = 1;
while (!q.empty()) q.pop();//清空队列
}
bool bfs (int t){
clr[t] = 1;
q.push(t);
while (!q.empty()) {
int head = q.front(); q.pop();
for (int i=1; i<=n; i++){
if (w[head][i] != 0 && clr[i] == 1 - clr[head]) continue;
if (w[head][i] != 0 && clr[i] == -1) {clr[i] = 1 - clr[head];q.push(i);}
if (w[head][i] != 0 && clr[i] == clr[head]) return false;
}
}
return true;
}
bool find(int p){
for (int i=1; i<=num_y-1; i++){
if (vis[i] == 0 && w[p][y[i]] != 0){
vis[i] ++;
if (l[y[i]] == 0 || find(l[y[i]])){
l[y[i]] = p;
return true;
}
}
}
return false;
}