P10378 [GESP202403 七级] 交流问题

题目

传送门

思路

看了看题解区,大部分dalao都是用二分图解决的,可是煮波不会QWQ
我于是在地上打了1h的滚加上看了看题解区里发现还可以用dfs解决

实现方法

就是遍历每个没有被标记的结点,把他们标记成true,然后遍历与他相邻的连通块,也就是DFS,A和B的学生数可以用奇偶性来判断,具体见代码。

代码

有注释

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5; 
int n,m,ans1=0,ans2=0,cnt1=0,cnt2=0;
vector<int>v[N]; 
bool f[N];
void dfs(int x,int s){
	if(v[x].size()==0)return;
	for(int i=0;i<v[x].size();i++){//遍历相邻的边
		if(!f[v[x][i]]){//如果没被遍历过
			f[v[x][i]]=true;//标记为true
			if(s%2==1){//借助奇偶性判断
				cnt2++;
			}
			else{//同理
				cnt1++;
			}
			dfs(v[x][i],s+1);//继续以他为起始点遍历
		}
	}
}
int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		if(!f[i]){//没被标记过
			f[i]=true;
			cnt1=cnt2=0;//初始化
			cnt1++;//第一个结点
			dfs(i,1);//DFS
			ans1+=min(cnt1,cnt2);//至少的取最小的
			ans2+=max(cnt1,cnt2);//至多的取最大的
		}
	}
	cout<<ans1<<' '<<ans2;
	return 0;
}

无注释

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5; 
int n,m,ans1=0,ans2=0,cnt1=0,cnt2=0;
vector<int>v[N]; 
bool f[N];
void dfs(int x,int s){
	if(v[x].size()==0)return;
	for(int i=0;i<v[x].size();i++){
		if(!f[v[x][i]]){
			f[v[x][i]]=true;
			if(s%2==1){
				cnt2++;
			}
			else{
				cnt1++;
			}
			dfs(v[x][i],s+1);
		}
	}
}
int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		if(!f[i]){
			f[i]=true;
			cnt1=cnt2=0;
			cnt1++;
			dfs(i,1);
			ans1+=min(cnt1,cnt2);
			ans2+=max(cnt1,cnt2);
		}
	}
	cout<<ans1<<' '<<ans2;
	return 0;
}
posted @ 2026-08-22 18:57  陈晨2011  阅读(3)  评论(0)    收藏  举报