Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //misaka will carry me to master
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <cmath>
- #include <utility>
- #include <cassert>
- #include <algorithm>
- #include <vector>
- #include <functional>
- #include <numeric>
- #include <set>
- #include <map>
- #define ll long long
- #define lb long double
- #define sz(vec) ((int)(vec.size()))
- #define all(x) x.begin(), x.end()
- #define pb push_back
- #define mp make_pair
- const lb eps = 1e-9;
- const ll mod = 1e9 + 7, ll_max = 1e18;
- //const ll mod = (1 << (23)) * 119 +1;
- const int MX = 2e5 +10, int_max = 0x3f3f3f3f;
- using namespace std;
- //negative trust
- //so i need a trie that does
- //xor all and max
- //easiest is a push/pull implicit segtree
- const int NN = MX*20;
- char flag[NN];
- int lc[NN], rc[NN], tag[NN];
- int root[MX];
- int xum[MX], grundy[MX];
- int color[MX];
- vector<int> adj[MX];
- int n;
- const int LG = 20, s = (1 << LG);
- #define lsb(x) (x&(-x))
- void push(int k, int a){
- if(tag[k]){
- if(a&tag[k]) swap(lc[k], rc[k]);
- if(lc[k]) tag[lc[k]] ^= tag[k];
- if(rc[k]) tag[rc[k]] ^= tag[k];
- }
- tag[k] = 0;
- }
- void pull(int k){
- if(flag[lc[k]] && flag[rc[k]]){
- flag[k] = 1;
- }
- }
- void dup(int& k){
- static int ind = 0;
- if(!k)
- k = ++ind;
- }
- void U(int p, int &k, int L, int R){
- dup(k);
- if(L + 1 == R){
- assert(L == p);
- //cout << "wave\n";
- flag[k] = 1;
- return ;
- }
- int mid = (L + R)/2;
- push(k, lsb(mid));
- if(p < mid) U(p, lc[k], L, mid);
- else U(p, rc[k], mid, R);
- pull(k);
- }
- void merge(int& k1, int k2, int d){
- if(min(k1, k2) == 0){
- k1 ^= k2;
- return ;
- }
- if(d == 0){
- return ;
- }
- push(k1, (1 << (d-1))); push(k2, (1 << (d-1)));
- merge(lc[k1], lc[k2], d-1);
- merge(rc[k1], rc[k2], d-1);
- pull(k1);
- }
- int mex(int k, int L, int R){
- if(L + 1 == R) return L;
- int mid = (L + R)/2;
- push(k, lsb(mid));
- if(flag[lc[k]]) return mex(rc[k], mid, R);
- else return mex(lc[k], L, mid);
- }
- void dfs(int u, int p){
- for(int v : adj[u]){
- if(v == p) continue;
- dfs(v, u);
- xum[u] ^= grundy[v];
- }
- if(color[u] == 0){
- U(xum[u], root[u], 0, s);
- }else{
- dup(root[u]);
- }
- for(int v : adj[u]){
- if(v == p) continue;
- if(root[v]){
- tag[root[v]] ^= xum[u] ^ grundy[v];
- merge(root[u], root[v], LG); //i hope
- //cout << "new root " << root[u] << "\n";
- }
- }
- grundy[u] = mex(root[u], 0, s);
- }
- vector<int> ans;
- void dfs2(int u, int p, int tot){
- tot ^= xum[u];
- if(tot == 0 && color[u] == 0){
- ans.pb(u);
- }
- for(int v : adj[u]){
- if(v != p){
- dfs2(v, u, tot^grundy[v]);
- }
- }
- }
- void solve(){
- cin >> n;
- for(int i = 1; i<=n; i++){
- cin >> color[i];
- }
- for(int i = 1; i<n; i++){
- int a, b;
- cin >> a >> b;
- adj[a].pb(b);
- b[adj].pb(a);
- }
- dfs(1, 0);
- //for(int i = 1; i<=n; i++){
- //cout << grundy[i] << " " ;
- //} cout << "\n";
- //for(int i = 1; i<=n; i++){
- //cout << xum[i] << " " ;
- //} cout << "\n";
- if(grundy[1] == 0){
- cout << "-1\n";
- }else{
- dfs2(1, 0, 0);
- sort(all(ans));
- for(int x : ans){
- cout << x << "\n";
- }
- }
- }
- int main(){
- cin.tie(0) -> sync_with_stdio(0);
- int T = 1;
- //cin >> T;
- while(T--){
- solve();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement