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;
}