CF977E Cyclic Components 题解

题目:CF977E Cyclic Components

图论-连通块-DFS-BFS

题目大意

给出一个有若干个连通块无向图,求有多少个连通块满足 该连通块构成一个环

一个环,就是一个形如下图的连通块,满足点数与边数相等,且不应有多余的边
image.png
第一个想到的就是 dfs 判环:如果要访问的节点 y y y 被访问过了,并且 y y y 为当前连通块遍历的第一个节点 t o p top top (也就是连通块遍历完了),return true;如果 y ≠ t o p y \ne top y=top return 0

dfs 代码

bool dfs(int x,int fa,int top)
{
	vis[x]=1;
	for(int i=0;i<e[x].size();++i)
	{
		int y=e[x][i];
		if(y==fa)continue;
		if(vis[y] && y!=top)return 0;
		if(y==top)return 1;
		bool flag=dfs(y,x,top);
		if(flag)return 1;
	}
	return 0;
}

写完发现过不了样例,又加了个 bfs 计算点数和边数,并判等

bool bfs(int s)
{
	queue <int> q;
	int cnt=0,tot=0;
	vist[s]=1,q.push(s);
	while(q.size())
	{
		int x=q.front();
		q.pop();
		++cnt;
		if(d[x]!=2)return 0;  // 判断度数,后面会讲
		for(int i=0;i<e[x].size();++i)
		{
			int y=e[x][i];
			++tot;
			if(vist[y])continue;
			vist[y]=1,q.push(y);
		}
	}
	tot>>=1;
	return cnt==tot;
}

提交上去又双叒叕在第三个点挂了,仔细想了想后,发现环中的每个节点度数都为 2 2 2 ,加了判断度数后才AC

完整代码:

#include<cstdio> 
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int Maxn=200000+20,inf=0x3f3f3f3f;
int n,m,ans;
bool vis[Maxn],vist[Maxn];
int d[Maxn];
vector <int> e[Maxn];
inline int read()
{
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return s*w;
}
bool dfs(int x,int fa,int top)
{
	vis[x]=1;
	for(int i=0;i<e[x].size();++i)
	{
		int y=e[x][i];
		if(y==fa)continue;
		if(vis[y] && y!=top)return 0;
		if(y==top)return 1;
		bool flag=dfs(y,x,top);
		if(flag)return 1;
	}
	return 0;
}
bool bfs(int s)
{
	queue <int> q;
	int cnt=0,tot=0;
	vist[s]=1,q.push(s);
	while(q.size())
	{
		int x=q.front();
		q.pop();
		++cnt;
		if(d[x]!=2)return 0;
		for(int i=0;i<e[x].size();++i)
		{
			int y=e[x][i];
			++tot;
			if(vist[y])continue;
			vist[y]=1,q.push(y);
		}
	}
	tot>>=1;
	return cnt==tot;
}
int main()
{
//	freopen("in.txt","r",stdin);
	n=read(),m=read();
	for(int i=1;i<=m;++i)
	{
		int x=read(),y=read();
		e[x].push_back(y);
		e[y].push_back(x);
		d[x]++,d[y]++;
	}
	for(int i=1;i<=n;++i)
	{
		if(vis[i])continue;
		bool flag=dfs(i,0,i) && bfs(i);
		if(flag)++ans;
		//printf("i = %d  %d\n",i,flag);
	}
	printf("%d\n",ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值