@atcoder - [email protected] Two Trees

目录

  • @[email protected]
  • @[email protected]
  • @accepted [email protected]
  • @[email protected]

@[email protected]

给定两棵树 A, B。现你需要构造一组值 (X1, X2, ..., XN)(两棵树编号相同的点对应权值相同),使得两棵树内任意子树的权值和的绝对值为 1。

无解输出 IMPOSSIBLE。

原题链接。

@[email protected]

由于权值和为 1,可以推算出每个结点的奇偶性。如果两棵树中同一结点权值奇偶性不同则无解。

考虑已知每个结点权值的奇偶性之后是否能够构造出一组解。
既然是构造题,从简原则,猜想偶点总是为 0,奇点总是为 1 或 -1。
手玩一下样例发现是对的。

那么相当于给每个奇点染黑白色,使得每棵子树内黑白点个数相差为 1。

然后就开始玄幻起来了。我们对于每个奇点 i,在两棵树 A, B 的结点 Ai, Bi 之间连一条边。
注意到此时新图中只有两棵树的根度数可能为奇数,所以我们从根出发跑欧拉路径。
如果欧拉路径中 Ai->Bi 则 i 为黑点(-1),否则 i 为白点(1)。

正确性理解起来不难:对于每个连通块(子树),进入连通块的广义 “入度” 与从连通块出的广义 “出度” 是相等的。
而子树向外只有两类边:连向父亲(只有一条);连向另一棵树。也就是连向另一棵树的边(奇点之间的边)入边与出边相差 1,就是我们的构造目标。

@accepted [email protected]

#include <cstdio>

const int MAXN = 200000;
const int MAXM = 8*MAXN;

struct edge{
    int to; bool tag;
    edge *nxt, *rev;
}edges[MAXM + 5], *adj[MAXN + 5], *ecnt = edges;

void addedge(int u, int v) {
    edge *p = (++ecnt), *q = (++ecnt);
    p->to = v, p->tag = false, p->nxt = adj[u], adj[u] = p;
    q->to = u, q->tag = false, q->nxt = adj[v], adj[v] = q;
    p->rev = q, q->rev = p;
}

int X[MAXN + 5], N;
void dfs(int x) {
    for(;adj[x];) {
        edge *p = adj[x]; adj[x] = adj[x]->nxt;
        if( p->tag ) continue;
        p->tag = p->rev->tag = true;
        dfs(p->to);
        if( x - p->to == -N ) X[x] = -1;
        else if( x - p->to == N ) X[p->to] = 1;
    }
}

int cnt[2][MAXN + 5];
int main() {
    scanf("%d", &N);
    int rt1;
    for(int i=1;i<=N;i++) {
        int x; scanf("%d", &x);
        if( x != -1 ) {
            addedge(x, i);
            cnt[0][x]++;
        }
        else rt1 = i;
    }
    for(int i=1;i<=N;i++) {
        int x; scanf("%d", &x);
        if( x != -1 ) {
            addedge(x + N, i + N);
            cnt[1][x]++;
        }
    }
    for(int i=1;i<=N;i++) {
        if( (cnt[0][i] - cnt[1][i]) & 1 ) {
            puts("IMPOSSIBLE");
            return 0;
        }
        if( !(cnt[0][i] & 1) )
            addedge(i, N + i);
    }
    dfs(rt1);
    puts("POSSIBLE");
    for(int i=1;i<=N;i++)
        printf("%d%c", X[i], (i == N ? '\n' : ' '));
}

@[email protected]

仿佛发现了比网络流建模更难的东西.jpg。
不愧是 AGC,轻易就出了一道人类智慧题。

有一个小细节:整棵树作为一棵子树,是没有向上连向父亲的边的。所以证明时还要特殊讨论一下(不过总之证得出来)。

原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/12234568.html

时间: 2024-08-01 23:06:21

@atcoder - [email protected] Two Trees的相关文章

@atcoder - [email&#160;protected] Contest with Drinks Hard

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定序列 T1, T2, ... TN,你可以从中选择一些 Ti,可以选择 0 个(即不选). 定义你选择的权值 = (满足 T[L...R] 都被选择的区间 [L, R] 的数量)-(你选择的 Ti 之和),你希望这个权值尽量大. 现在有 M 次询问,每次询问假如将 T[Pi] 修改

@atcoder - [email&#160;protected] Colorful Tree

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 题面明天起来补... @[email protected] 跟颜色有关,虽然题目中说是要"修改"实际上每一个询问之间是独立的,即修改不会有时效性. 所以不难想到可以使用树上莫队. 首先将边的颜色与边权下放至点.然后莫队时,统计出区间内每个点的点权(就是下放的边权)和 S.区间

@atcoder - [email&#160;protected] Gachapon

目录 @[email protected] @solution - [email protected] @accepted code - [email protected] @solution - [email protected] @accepted code - [email protected] @[email protected] @[email protected] 一个随机数发生器会生成 N 种数. 第 i 种数有参数 Ai,记 SA = ∑Ai,随机数发生器会有 Ai/SA 的概率

@atcoder - [email&#160;protected] RNG and XOR

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定一个值域在 [0, 2^N) 的随机数生成器,给定参数 A[0...2^N-1]. 该生成器有 \(\frac{A_i}{\sum A}\) 的概率生成 i,每次生成都是独立的. 现在有一个 X,初始为 0.每次操作生成一个随机数 v 并将 X 异或 v. 对于每一个 i ∈ [0

@atcoder - [email&#160;protected] Simple Subsequence Problem

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定由若干长度 <= N 的 01 字符串组成的集合 S.请找到长度最长的串 t(如果有多个选字典序最小的),使得存在 >= K 个 S 中的字符串,使得 t 是这些字符串的子序列. 原题题面. @[email protected] 先看看怎么检验串 t 是否为某个串 s 的子序列:

@atcoder - [email&#160;protected] Next or Nextnext

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定一个长度为 N 的序列 a,问有多少排列 p,满足对于每一个 i,都有 \(a_i = p_i\) 或 \(a_i = p_{p_i}\) 成立. 原题传送门. @[email protected] 为了更直观地理解问题,不妨建个图:连有向边 \(i -> p_i\). 对于任意序

@atcoder - CODE FESTIVAL 2017 Final - [email&#160;protected] Tree MST

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定 N 个点,第 i 点有一个点权 Xi,再给定一棵边带权的树,第 i 条 (Ai, Bi) 边权为 Ci. 构建一个完全图,完全图中边 (i, j) 的边权为 dist(i, j) + Xi + Xj,其中 dist(i, j) 是点 i 与点 j 在树上的距离. 求该完全图的最小

$*和[email&#160;protected]之间区别代码分析

#!/bin/bash set 'apple pie' pears peaches for i in $*           /*单引号被去掉,循环单个字符输出*/ do echo $i done [[email protected] Ex_14.02-14.31]# sh 14-14-1 apple pie pears peaches -------------------------------------------------------------- #!/bin/bash set

[email&#160;protected]一个高效的配置管理工具--Ansible configure management--翻译(六)

无书面许可请勿转载 高级playbook Finding files with variables All modules can take variables as part of their arguments by dereferencing them with {{ and }} . You can use this to load a particular file based on a variable. For example, you might want to select a