1. 题目
RC-u4 章鱼图的判断 - 2024 睿抗机器人开发者大赛CAIP-编程技能赛-本科组(省赛) (pintia.cn)
2.具体代码
//思路:并查集
//如果在输入边之前两点就联通了,说明就形成了环
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int fa[N],huan[N]; //根节点,根节点形成环的个数
int dis[N]; //记录从起点到其他点的顶点个数
vector<int> g[N]; //存图
//并查集模板(初始化放在程序里面了)
//求父节点
int find(int i){
if(fa[i]!=i)
fa[i]=find(fa[i]);
return fa[i];
}
//两点建立关系
void join(int i,int j){
int fa_i=find(i);
int fa_j=find(j);
if(fa_i!=fa_j){
fa[fa_i]=fa_j;
}
}
//bfs求两点之前的顶点数
//(注意不是st和ed直接相连的长度,遍历方向应该是不和ed相连的方向)
//如果是栈顶元素为st,紧邻它的是ed,应该continue
int bfs(int st,int ed){
memset(dis,0,sizeof(dis));
queue<int> q;
dis[st]=1;
q.push(st);
while(!q.empty()){
int x=q.front();
q.pop();
for(int i:g[x]){
if(!dis[i]){
if(x==st&&i==ed)
continue;
if(x!=st&&i==ed){
return dis[x]+1;
}
dis[i]=dis[x]+1;
q.push(i);
}
}
}
return dis[ed];
}
int main(void){
int t;
cin>>t;
while(t--){
int n,m;
int st,ed;
cin>>n>>m;
//初始化
for(int i=1;i<=n;i++){
fa[i]=i;
g[i].clear();
huan[i]=0;
}
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
if(find(a)==find(b)){ //两者相连形成环
huan[find(a)]++;
st=a,ed=b; //记录环的起始和终止节点
}else{
huan[find(b)]+=huan[find(a)];
join(a,b); //a的父节点设为b
}
}
int cnt=0; //环的个数
//判断是否有且只有一个环
for(int i=1;i<=n;i++){
if(find(i)==i&&huan[i]==1){
cnt++;
}
}
if(cnt!=1){
cout<<"No "<<cnt;
if(t!=0)
cout<<endl;
continue;
}
int ans=bfs(st,ed);
cout<<"Yes "<<ans;
if(t!=0)
cout<<endl;
}
return 0;
}