P10179 题解
\text{solution}
比较简单的构造题。
考虑点
考虑用并查集将所有父节点相同的节点合并,这样可以得到若干个集合,显然,当只出现了一个集合时,构造无解。
接下来处理集合之间如何连边,发现对于一个集合
\text{code}
int n,m;
int fa[maxn];
int siz[maxn];
int find(int a){
if(fa[a]==a){
return fa[a];
}
return fa[a]=find(fa[a]);
}
void merge(int a,int b){
int na=find(a),nb=find(b);
if(na==nb){
return ;
}
fa[na]=nb;
siz[nb]+=siz[na];
}
map<int,int> mp;
int cnt[maxn],tot;
void solve(){
for(int i=1;i<=n;i++){
cnt[i]=0;
}
mp.clear();
tot=0;
n=read(),m=read();
for(int i=1;i<=n;i++){
fa[i]=i;
siz[i]=1;
}
for(int i=1;i<=m;i++){
int u=read(),v=read();
merge(u,v);
}
if(siz[find(1)]==n){
puts("No");
return ;
}
for(int i=1;i<=n;i++){
if(!mp[find(i)]){
mp[find(i)]=1;
cnt[++tot]=find(i);
}
}
puts("Yes");
int flag=0;
for(int i=1;i<=n;i++){
if(find(i)!=cnt[1]){
flag=i;
break;
}
}
for(int i=1;i<=n;i++){
if(find(i)!=cnt[1]){
printf("%lld %lld\n",i,cnt[1]);
}
else if(i==find(i)){
continue ;
}
else{
printf("%lld %lld\n",i,flag);
}
}
return ;
}