• AGC 018 F


    F - Two Trees

    链接

    题意:

      给定两棵都是N个节点的有根树,节点均从1~N标号。给每个标号定一个权值(类似一号点的权值是x,那么两棵树中1号点的权值都是x),使在两棵树满足以任意节点为根的子树的权值和为1或-1。输出任意一种解或判断无解,N<=100000。

    分析:

      欧拉回路。

      首先每棵子树的权值和都-1或者1,,如果知道了每个点有多少个子节点,那么就可以知道他的奇偶性(奇数个儿子=>权值为偶数,偶数个儿子=>权值为奇数)。现在可以判断无解了:如果同一个节点在两棵树内的奇偶性不同。

      然后建立一个0点,将两棵树连起来;然后一个标号的点在两棵树上是奇点,那么有第一棵树的这个点向第二棵树的这个点连一条边(x->x+n)。然后跑欧拉回路,对于从第一棵树到第二颗树的点,权值为1,否则为-1,偶点为0。

      具体的解释证明,画一下,挺对的。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 500005;
    struct Edge{
        int fr, to, nxt; 
    }e[N << 1];
    int head[N], f1[N], f2[N], c1[N], c2[N], sk[N << 1], ans[N], top = 0, En = 1;
    bool vis[N << 1];
    
    inline void add_edge(int u,int v) {
    //    cout << u << " " << v << "
    ";
        ++En; e[En].fr = u, e[En].to = v, e[En].nxt = head[u]; head[u] = En;
        ++En; e[En].fr = v, e[En].to = u, e[En].nxt = head[v]; head[v] = En;
    }
    void dfs(int u) {
        while (1) {
            int k = head[u]; 
            if (!k) break;
            head[u] = e[k].nxt;
            if (!vis[k]) {
                vis[k] = vis[k ^ 1] = 1;
                dfs(e[k].to);
                sk[++top] = k;
            }
        }
    }
    int main() {
        freopen("1.txt", "r", stdin);
        int n = read();
        for (int i = 1; i <= n; ++i) {
            int x = read();
            if (x == -1) x = 0;
            f1[i] = x, c1[x] ++;
            add_edge(x, i);
        }
        for (int i = 1; i <= n; ++i) {
            int x = read();
            if (x == -1) x = 0;
            f2[i] = x, c2[x] ++;
            if (x == 0) add_edge(x, i + n);
            else add_edge(x + n, i + n);
        }
        for (int i = 1; i <= n; ++i) {
            if (c1[i] % 2 != c2[i] % 2) { puts("IMPOSSIBLE"); return 0; }
            if ((c1[i] & 1) && (c2[i] & 1)) ans[i] = 0;
            else add_edge(i, i + n);
        }
        puts("POSSIBLE");
        dfs(0);
        for (int i = top; i >= 1; --i) {
            int k = sk[i];
            if (e[k].fr + n == e[k].to) ans[e[k].fr] = 1;
            if (e[k].fr - n == e[k].to) ans[e[k].fr - n] = -1;
        }
        for (int i = 1; i <= n; ++i) {
            printf("%d ", ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    [ AHOI 2013 ] 作业 & [ BZOJ 3809 ] Gty的二逼妹子序列
    [ CQOI 2018 ] 异或序列
    [ Luogu 3709 ] 大爷的字符串题
    偷学笔记
    ZJOI2019 补题记录
    Bluestein's Algorithm
    「九省联考 2018」制胡窜
    Codeforces 1349D Bear and Biscuits
    AGC021E Ball Eat Chameleons
    AGC036F Square Constraints
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10279477.html
Copyright © 2020-2023  润新知