题意:
有n个人,其中有m组,两两互斥,现在要分成两个班,但最终求的确是最多有多少对不互斥的。
题目:
链接:https://ac.nowcoder.com/acm/contest/16741/F
来源:牛客网
The big day has fifinally arrived: today you are going to form groups of two in which you will do the end-of-the-year project. When you arrive at school, you learn that the teacher of the other class is sick, and that your teacher, Mr. B.A.P. Cee, will also have to make groups for the other class. Mr. B.A.P. Cee is a smart guy and realizes that he can use these unfortunate circumstances to his advantage.
Ending up with groups of one should be avoided at all cost, so mixing the students of the two classes may avoid this situation. However, while it is easy to pair up two students from the same class, it is more diffiffifficult to match up students from difffferen classes. Throughout the years there has been a lot of rivalry between the two groups, and many students dislike students in the other class. Mr. B.A.P. Cee knows which pairs of students will result in a fifight and a failed project.
You are given a list of pairs of students who cannot work together. How many disjoint groups of two can Mr. B.A.P. Cee make that will not result in a failed project?
输入描述:
The input consists of:
• A line with two integers n (1 ≤ n ≤ 105), the number of students, and m (0 ≤ m ≤ 2 · 105), the number of pairs of students who cannot work together.
• m lines, each with two distinct integers i and j (1 ≤ i, j ≤ n, i = j), giving a pair of students who cannot work together.
Students are identifified by the numbers 1 through n. It is guaranteed that it is possible to split the students into two classes in such a way that all students from the same class get along.
输出描述:
Output the number of pairs of students Mr. B.A.P. Cee can make without making any pair of students who cannot work together.
示例1
输入
3 2
1 2
3 1
输出
1
示例2
输入
5 6
1 4
2 4
3 4
1 5
2 5
3 5
输出
2
示例3
输入
6 6
1 4
2 5
3 6
1 5
3 5
2 6
输出
3
分析:
1.因为这道题求的是两个不互斥的对数,最大能有多少对不互斥的。所以我们只需要保证区分后,两个班里面不存在不互斥的就可以了。
2.这里我直接用vector数组处理,两两互斥的状况,建图,即相邻互斥,隔代在同一个班即可
3. 分完班之后,按理来说,直接每个班成对即可,即su/2+sm/2;但当两个并不是都互斥时,两个班里只要存在一对不互斥时,此时这两个就可以成为一对不互斥,此时的对数就是n/2,判断条件即为su*sm==m
4. 前面说了题意并不需要可以用唯一方法分出两个班,还有一种是用并查集扩展域,用并查集及扩展域存储同类关系和异类关系;也贴在下面
AC代码:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;
typedef long long ll;
const int M=2e5+10;
int n,m,a,b;
vector<int>ve[M];
int vis[M];
void dfs(int u,int pre,int color){
vis[pre]=color;
for(int i=0;i<ve[pre].size();i++){
int k=ve[pre][i];
if(u==k||vis[k]!=-1) continue;
dfs(pre,k,color^1);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
vis[i]=-1;
for(int i=0;i<m;i++){
cin>>a>>b;
ve[a].push_back(b);
ve[b].push_back(a);
}
int su=0,sm=0;
for(int i=1;i<=n;i++){
if(vis[i]==-1){
dfs(0,i,0);
}
if(vis[i]==0) ++su;
else ++sm;
}
if(su*sm==m) printf("%d\n",su/2+sm/2);
else printf("%d\n",n/2);
return 0;
}
/**有一种情况需要特判:
如果两班均是奇数个人,且有一班中某人的敌人数小于另一班人数,则说明此人可以与另一班某同学组组;*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<int> vec,tn[100005];//vec存一班的同学编号,tn[i]存储i号同学的敌人
int fa[200005];//扩展域并查集
int find(int x)//此题中,find(x)的返回值为1或0
{
if(fa[x]!=x)return fa[x]=find(fa[x]);
return x;
}
int main()
{
int n,m;
int a,b;
cin>>n>>m;
for(int i=1;i<=n;i++)fa[i]=1;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
if(a>b)swap(a,b);
tn[a].push_back(b);
tn[b].push_back(a);
fa[b]=a+n;
fa[b+n]=a;
}
int s,l;s=l=0;//l与s存储两班人数
for(int i=1;i<=n;i++)
{
if(find(i))l++;
else s++,vec.push_back(i);
}
if(s&1&&l&1)
{
for(int i=0;i<vec.size();i++)
if(tn[vec[i]].size()!=l){s--,l++;break;}
}
printf("%d",s/2+l/2);
return 0;
}