CF1817B Fish Graph

题目大意

定义了一个鱼图,求是否存在并输出环和两点的边。

题意分析

直接暴力,但是需要加一点点小优化,具体如下:

  1. 环的检测:我们首先需要在图中找到一个环,如果遇到了一个已经访问过的节点,并且该节点不是当前路径的父节点,就形成了一个环。
  2. 检查环的特殊节点:鱼图的要求是环中的某个节点,除了参与环的连接,还必须有两条指向环外的边。
  3. 遍历所有可能的环:环的起始节点可能是任意的,因此我们需要遍历所有节点,尝试从每个节点出发找到一个环,并判断该环是否符合鱼图的要求。同时由于是环,所以这个点必须有被四个点连接
    具体可参考代码及注释理解。

CODE

#include<bits/stdc++.h>
#define wk(x) write(x),putchar(' ')
#define wh(x) write(x),putchar('\n')
#define ll long long
#define ull unsigned long long
#define ri register int
#define INF 2147483647
#define mod 998244353
#define N 50005
#define NO printf("No\n")
#define YES printf("Yes\n")

using namespace std;
int n,m,k,jk,ans,sum,num,cnt,tot;
int head[N],dis[N],vis[N],wis[N],f[N];

void read(int &x)
{
	x=0;int ff=1;char ty;
	ty=getchar();
	while(!(ty>='0'&&ty<='9'))
	{
		if(ty=='-') ff=-1;
		ty=getchar();
	}
	while(ty>='0'&&ty<='9')
		x=(x<<3)+(x<<1)+ty-'0',ty=getchar();
	x*=ff;return;
}

void write(int x){
	if(x==0){
		putchar('0');
		return;
	}
	if(x<0){
		x=-x;
		putchar('-');
	}
	char asd[201];int ip=0;
	while(x) asd[++ip]=x%10+'0',x/=10;
	for(int i=ip;i>=1;i--) putchar(asd[i]);
	return;
}

struct lenovo{
	int to,nxt,val;
}v[N*2];

void add(int x,int y)
{
	v[++cnt].to=y;
	v[cnt].nxt=head[x];
	head[x]=cnt;
}

void dfs(int x,int y,int z){
	if(tot) return;f[++num]=x;vis[x]=1;//加入堆中。
	for(int i=head[x];i&&!tot;i=v[i].nxt){
		int u=v[i].to;if(u==y) continue;
		if(u==z&&y!=z){//到达原点。
			memset(dis,0,sizeof dis);int pop=0;//初始化。
			for(int j=1;j<=num;j++) dis[f[j]]=1;//标记堆中的元素。
			for(int j=head[z];j&&pop<2;j=v[j].nxt)
				if(!dis[v[j].to]) pop++;//取另外两点。
			if(pop<2) continue;//不符合条件就退出。
			YES;wh(num+2);//输出答案。
			for(int j=num;j>1;j--) wk(f[j]),wh(f[j-1]);
			wk(z),wh(x);pop=0;
			for(int j=head[z];j&&pop<2;j=v[j].nxt)
				if(!dis[v[j].to]) wk(z),wh(v[j].to),pop++;
			tot=1;return;
		}if(!vis[u]) dfs(u,x,z);//继续遍历。
	}num--;//弹出堆顶。
}

signed main()
{
	read(jk);while(jk--){
		read(n),read(m);int x,y;cnt=0;
		memset(head,0,sizeof head);//记得初始化。
		memset(wis,0,sizeof wis);
		for(int i=1;i<=m;i++){
			read(x),read(y);
			add(x,y),add(y,x);
			wis[x]++,wis[y]++;//将出度和入度加一。
		}tot=0;
		for(int i=1;i<=n&&!tot;i++){
			if(wis[i]<4) continue;//一定不可能是。
			memset(vis,0,sizeof vis);
			dfs(i,0,i);num=0;//暴力。
		}
		if(!tot) NO;//无解的情况。
	}
	return 0;
}
posted @ 2025-11-22 16:21  Red_river_hzh  阅读(6)  评论(0)    收藏  举报