题意:给一张图,求一颗生成树,使1号点度数恰为D
边分成三类,必选的边,1号点上可选的边,其他边
必选边先连上,1点剩下的边随意连直到度数为D,其他边补全生成树
必选边怎么求?比赛时用了tarjan求桥(疯狂WA37),因为一些不是桥的结构也会有(任选的)必选边,比如三角形
所以遍历和1点相连的边,dfs求出通过该边能到达的边,即选了该边以后这些边都是任选了
这样就对了
/*
* Author : GhostCai
* Expecto Patronum
*/
#include<bits/stdc++.h>
using namespace std;
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
cerr << " " << H;
debug_out(T...);
}
#define debug(...) \
cerr << __LINE__ << " [" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define eep(x,y) for(int x=head[y];x;x=e[x].next)
inline void shit() {puts("NO");}
inline void good() {puts("YES");}
inline int rd(){
int ret=0,f=1;char c;
while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
while(isdigit(c))ret=ret*10+c-'0',c=getchar();
return ret*f;
}
#define pc putchar
#define space() pc(' ')
#define nextline() pc('\n')
void pot(int x){if(!x)return;pot(x/10);pc('0'+x%10);}
void out(int x){if(!x)pc('0');if(x<0)pc('-'),x=-x;pot(x);}
const int MAXN = 400005;
int n,m,D;
struct Edge{
int next,to;
}e[MAXN<<1];
int ecnt=1,head[MAXN];
inline void add(int x,int y){
e[++ecnt]={head[x],y};
head[x]=ecnt;
}
bool vis[MAXN<<1];
//pair<pair<int,int>,int> edg[MAXN],tot;
int ind[MAXN];
int fa[MAXN];
int fnd(int x){return x==fa[x]?x:fa[x]=fnd(fa[x]);}
void cat(int x,int y){x=fnd(x);y=fnd(y);fa[x]=y;}
int ans[MAXN][2],anscnt;
void pushans(int x,int y){
ans[++anscnt][0]=x;
ans[anscnt][1]=y;
}
//int dfn[MAXN],low[MAXN],dcnt;
//int cut[MAXN];
//
//void tarjan(int u,int fa){
// dfn[u]=low[u]=++dcnt;
// for(int i=head[u];i;i=e[i].next){
// int v=e[i].to;
// if(!dfn[v]){
// tarjan(v,u);
// low[u]=min(low[u],low[v]);
// if(low[v]>dfn[u]) cut[i]=cut[i^1]=1;
// }
// else if(v!=fa)
// low[u]=min(low[u],dfn[v]);
// }
//}
bool vv[MAXN];
void dfs(int x){
vv[x]=1;
eep(i,x){
int v=e[i].to;
if(vv[v]) continue;
dfs(v);
}
}
void solve(){
n=rd();m=rd();D=rd();
rep(i,1,n) fa[i]=i;
int x,y;
rep(i,1,m){
x=rd();y=rd();
add(x,y);
add(y,x);
}
// tarjan(1,-1);
int cnt1=0;
vv[1]=1;
eep(i,1){
int v=e[i].to;
if(vv[v]) continue;
cnt1++;
pushans(1,v);
vis[i]=1;
cat(1,v);
dfs(v);
}
// eep(i,1){
// if(vis[i]) continue;
// if(!cut[i]) continue;
// int v=e[i].to;
// if(fnd(1)==fnd(v)) continue;
// pushans(1,v);cnt1++;vis[i]=1;vis[i^1]=1;
// cat(1,v);
// }
eep(i,1){
if(cnt1>=D) break;
if(vis[i]) continue;
int v=e[i].to;
if(fnd(1)==fnd(v)) continue;
cat(1,v);
vis[i]=1;vis[i^1]=1;
pushans(1,v);cnt1++;
}
// debug(cnt1);
if(cnt1!=D){
shit();return;
}
for(int i=2;i<=ecnt;i++){
if(vis[i]) continue;
int u=e[i^1].to,v=e[i].to;
if(u==1||v==1) continue;
if(fnd(u)==fnd(v)) continue;
cat(u,v);
pushans(u,v);
vis[i]=1;vis[i^1]=1;
}
rep(i,1,n){
if(fnd(i)!=fnd(1)){
// debug(fnd(i),fnd(1));
// debug(i);
shit();
return;
}
}
good();
rep(i,1,n-1){
printf("%d %d\n",ans[i][0],ans[i][1]);
}
}
int main(){
int T=1;
while(T--){
solve();
}
return 0;
}