Loading

题解:P10921 Happybob's Puzzle (UBC001A)

Happybob's Puzzle (UBC001A)

思路

黑白染色:对树上的点进行染色,相邻点颜色不同,那么颜色不同的点间的距离一定是奇数。也就是说要求排列中的任意相邻点的颜色不同。


思路有了还需要解决以下问题:

  • 怎么判断是否有解?

若黑色和白色点数量之差不大于 \(1\),那么就有解。否则排列内会有相邻点颜色相同,即它们之间的距离为偶数。

  • 怎么输出?

用两个优先队列交替从小到大输出,若两个颜色的点数量不同,从点数量多的队列开始输出,否则先输出第一个点序号小的。


时间复杂度:\(O(Tn\log n)\)


代码内有详细注释可以参照。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n; //点数 
priority_queue<ll, vector<ll>, greater<ll>> cl[2]; //用以记录两种颜色集合有的点 
vector<ll> e[1000005]; //邻接表存图 
void clear() {
	for(int i=1; i<=n; i++) e[i].clear();
	while(!cl[0].empty()) cl[0].pop(); //优先队列的清空 
	while(!cl[1].empty()) cl[1].pop();
}
void dfs(ll u, ll fa, ll nowcl) {
	cl[nowcl].push(u); //把当前元素放入所属队列 
	for(ll v:e[u]) { //相当于枚举 u 的出边所到达的点的编号 
		if(v==fa) continue;
		dfs(v, u, 1-nowcl);
	}
}
void solve() {
	ll u, v;
	cin >> n;
	clear(); //多测别忘了清空 
	for(int i=1; i<n; i++) {
		cin >> u >> v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	dfs(1, 0, 0);
	ll k=0, check=cl[0].size()-cl[1].size();
	if(abs(check)<=1) { //两个队列内元素数量差不大于 1 则可以构成序列 
		//确定从哪个队列开始 
		if(cl[0].size()<cl[1].size()) k=1;
		else if(!cl[0].empty()&&!cl[1].empty()&&cl[1].top()<cl[0].top()) k=1;
		//按顺序输出 
		while(cl[k].size()) {
			cout << cl[k].top() << " ";
			cl[k].pop();
			k=1-k;
		}
	} else {
		cout << -1;
	}
}
int main(){
	ios::sync_with_stdio(0);
	ll t;
	cin >> t;
	while(t--) {
		solve();
		cout << endl;
	}
	return 0;
}
posted @ 2024-08-25 12:16  Anins  阅读(20)  评论(0)    收藏  举报  来源