*题解:CF2133E I Yearned For The Mines

原题链接

解析

不难发现对于一条链,直接从一个端点 check 到另一个就可以。进而发现如果要保证找到,那么每个点都需要 check 一次。结合操作次数的限制,问题变成了用不超过 \(\lfloor \frac{n}{4}\rfloor\) 次操作 2 把树分割成若干条链。

于是就会有一个想法,对于所有儿子个数为 2 的点,让它对两个儿子子树中导出的链进行连接,这意味着父亲必须断边,而对于所有的儿子个数大于等于 \(3\) 的点,对其断边,当然断边之后就不算是父亲的儿子了。那么最坏情况就是每四个点做一次操作,满足 \(\lfloor \frac{n}{4}\rfloor\) 的限制。

代码

感觉写得一坨,不建议看。

/*
*/
#include<bits/stdc++.h>
#define eps 0.000001
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<ll,int> pii;
const int N = 2e5 + 5,M = 3.2e4 + 5;
vector<int> t[N];
bool op[N],ist[N];
int k,f[N],lf[N],cnt[N]; 
vector<int> v;
struct S{
	int u,v,tp;
};
vector<S> lst;
void dfs(int x,int fa){
	f[x] = fa;
	bool tp = false;
	vector<int> pos; 
	for(int nx : t[x])if(nx != fa){
		dfs(nx,x);
		cnt[x] += !op[nx];
		tp |= ist[nx];
		if(!op[nx]){
			pos.push_back(lf[nx]);
		}
	}
	if(!cnt[x]) lf[x] = x; 
	else if(pos.size() == 1) lf[x] = pos[0];
	if(cnt[x] >= 3 || tp){
		op[x] = true;
		for(int nx : t[x])if(nx != fa && !op[nx] && cnt[nx] <= 1){
			lst.push_back({lf[nx],nx,nx});
		}
		v.push_back(x);
		k++;	
	}else if(cnt[x] == 2){ 
		lst.push_back({pos[0],pos[1],x});
		ist[x] = true;
	}else if(cnt[x] == 1 && x == 1){
		lst.push_back({pos[0],x,x});
	}
}
void print(int x,int tp){
	cout<<1<<" "<<x<<'\n';
	if(x == tp) return;
	print(f[x],tp);
}
void rprint(int x,int tp){
	if(x == tp) return;
	rprint(f[x],tp);
	cout<<1<<" "<<x<<'\n';
}
int main(){
//	freopen("in.txt","r",stdin);
//	freopen("out1.txt","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int T;
	cin>>T;
	while(T--){
		int n;
		cin>>n;
		k = n;
		for(int i=1;i<n;i++){
			int u,v;
			cin>>u>>v;
			t[u].push_back(v);
			t[v].push_back(u);
		}
		dfs(1,0);
		cout<<k<<'\n';
		for(int i : v){
			cout<<2<<" "<<i<<'\n';
		}
		for(int i : v){
			cout<<1<<" "<<i<<'\n';
		}
		for(S l : lst){
			print(l.u,l.tp);
			rprint(l.v,l.tp);
		}
		if(!cnt[1]) cout<<1<<" "<<1<<'\n';
		lst.clear();
		v.clear();
		for(int i=1;i<=n;i++){
			lf[i] = 0;
			t[i].clear();
			ist[i] = false;
			cnt[i] = 0;
			op[i] = 0;
		}
	} 
	return 0;
}
/*
*/
posted @ 2025-08-25 11:31  yutar  阅读(38)  评论(0)    收藏  举报