CF1817B Fish Graph
题目大意
定义了一个鱼图,求是否存在并输出环和两点的边。
题意分析
直接暴力,但是需要加一点点小优化,具体如下:
- 环的检测:我们首先需要在图中找到一个环,如果遇到了一个已经访问过的节点,并且该节点不是当前路径的父节点,就形成了一个环。
- 检查环的特殊节点:鱼图的要求是环中的某个节点,除了参与环的连接,还必须有两条指向环外的边。
- 遍历所有可能的环:环的起始节点可能是任意的,因此我们需要遍历所有节点,尝试从每个节点出发找到一个环,并判断该环是否符合鱼图的要求。同时由于是环,所以这个点必须有被四个点连接。
具体可参考代码及注释理解。
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;
}
本文来自博客园,作者:Red_river_hzh,转载请注明原文链接:https://www.cnblogs.com/Red-river-hzh/p/19257066

浙公网安备 33010602011771号