Loading

CF453C Little Pony and Summer Sun Celebration (生成树+构造)

CF453C Little Pony and Summer Sun Celebration

生成树+构造

看看一个点的奇偶性意味着什么。意味着奇数的点必须经过至少一次,而偶数不用经过。那么所有奇数的点两两路径必须构成一个连通块。然后就可以开始想构造了。

考虑连通块上的任意一棵生成树,如果一个非根节点走完子树后次数不满足条件,可以往父亲走一步再走回来,那么这个节点就满足条件了。

发现根节点无法用这个策略,但是如果根节点不满足条件,可以把开头的根节点去掉,随便从一个儿子开始就可以了。

输出答案前要检查所有条件是否满足,还有可以加些特判,这里就不说了。

复杂度 \(O(n)\)

#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define mk std::make_pair
#define fi first
#define se second
#define pb push_back

using i64 = long long;
using ull = unsigned long long;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
const int N = 1e5 + 10;
int n, m, rt, flg;
int vis[N], cnt[N], a[N], t[N];
std::vector<int> e[N];
void dfs(int u, int fa) {
	t[u] = 1;
	for(auto v : e[u]) {
		if(v == fa || t[v]) continue;
		dfs(v, u);
		vis[u] |= vis[v];
	}
}
std::vector<int> pa;
void print(int u, int fa) {
	t[u] = 1;
	pa.pb(u);
	cnt[u]++;
	for (auto v : e[u]) {
		if(v == fa || !vis[v] || t[v]) continue;
		print(v, u);
		pa.pb(u);
		cnt[u]++;
	}
	if(u == rt) {
		if((cnt[u] & 1) != a[u]) cnt[u]--, flg = 1;
	} else if((cnt[u] & 1) != a[u]) {
		cnt[u]++, cnt[fa]++;
		pa.pb(fa), pa.pb(u);
	}
}
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
	std::cin >> n >> m;
	for (int i = 1; i <= m; i++) {
		int u, v;
		std::cin >> u >> v;
		e[u].pb(v), e[v].pb(u);
	}	
	bool ok = 1;
	for (int i = 1; i <= n; i++) {
		std::cin >> a[i];
		vis[i] = a[i];
		if(rt && a[i]) ok = 0;
		if(a[i]) rt = i;
	}
	if(!m && !ok) {
		std::cout << "-1\n";
		return 0;
	} else if(!rt) {
		std::cout << "0\n";
		return 0;
	}
	dfs(rt, 0);

	memset(t, 0, sizeof(t));
	print(rt, 0);
	for(int i = 1; i <= n; i++) {
		if((cnt[i] & 1) != a[i]) {
			std::cout << "-1\n";
			return 0;
		}
	}
	std::cout << pa.size() - flg << "\n";
	for(int i = flg; i < pa.size(); i++) std::cout << pa[i] << " ";
	return 0;
}
posted @ 2024-07-03 14:07  Fire_Raku  阅读(5)  评论(0编辑  收藏  举报