Codeforces Round #544 (Div. 3) F2. Spanning Tree with One Fixed Degree

题意:给一张图,求一颗生成树,使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;
}

posted @ 2021-01-15 22:51  GhostCai  阅读(53)  评论(0编辑  收藏  举报