[APIO2007] 风铃
题目链接
可能是个树上 DP?指针真好玩 23333。
首先对于所有玩具如果有深度差超过 1 的就是无解(在这里贡献 WA * 3),所以 dfs 一遍记录深度是有必要的……
然后如果有一个点的两颗子树中都含有最小、最大深度,那么这种情况也是无解,可以令同时含有两种深度的子树 tag = 1。
然后考虑最少交换次数,对于每一个节点的左右子树,三种情况需要交换:
1. 左边全是小深度的,右边全是大深度的
2. 左边全是小深度的,右边大小深度都有
3. 左边大小深度都有,右边全是大深度的
root->cnt = left_child->cnt + right_child->cnt + 本次是否需要交换(0 or 1)。
所以代码判的挺多的……
1 #include <queue> 2 #include <cstdio> 3 #include <cctype> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 using namespace std; 8 9 const int maxn = 200000 + 10; 10 int n, in_deg[maxn], maxx, minn, ans, node_num; 11 12 struct Node { 13 int deep, cnt, tag, type; 14 Node *lchild, *rchild; 15 16 Node() { type = cnt = deep = 0, lchild = rchild = NULL; } 17 ~Node() {}; 18 } node[maxn], *p_root; 19 20 inline int read() { 21 register char ch = 0; register int w = 0, x = 0; 22 while( !isdigit(ch) ) w |= (ch == '-'), ch = getchar(); 23 while( isdigit(ch) ) x = (x * 10) + (ch ^ 48), ch = getchar(); 24 return w ? -x : x; 25 } 26 27 inline void Set_deep(Node *x) { 28 if( x->lchild != NULL ) x->lchild->deep = x->deep + 1, Set_deep(x->lchild); 29 if( x->rchild != NULL ) x->rchild->deep = x->deep + 1, Set_deep(x->rchild); 30 } 31 32 inline void Deep_fs(Node *x) { 33 if( x->lchild == NULL && x->rchild == NULL ) return ; 34 if( x->lchild != NULL ) Deep_fs(x->lchild); 35 if( x->rchild != NULL ) Deep_fs(x->rchild); 36 if( x->lchild->tag && x->rchild->tag ) ans = -1; 37 if( x->lchild->type ^ x->rchild->type ) x->tag = 1; 38 else if( x->lchild->tag | x->rchild->tag ) x->tag = 1; 39 else if( x->lchild->deep != x->rchild->deep ) x->tag = 1; 40 x->cnt = x->lchild->cnt + x->rchild->cnt; 41 x->deep = max(x->lchild->deep, x->rchild->deep); 42 if( x->lchild->tag ^ x->rchild->tag ) { 43 if( x->lchild->tag && x->lchild->deep == x->rchild->deep ) ++x->cnt; 44 if( x->rchild->tag && x->lchild->deep < x->rchild->deep ) ++x->cnt; 45 } else if( x->lchild->deep < x->rchild->deep ) ++x->cnt; 46 } 47 48 int main(int argc, const char *argv[]) 49 { 50 freopen("..\\nanjolno.in", "r", stdin); 51 freopen("..\\nanjolno.out", "w", stdout); 52 53 scanf("%d", &n), node_num = n, minn = 2e9; 54 for(int l, r, i = 1; i <= n; ++i) { 55 l = read(), r = read(); 56 if( l == -1 ) node[++node_num].type = 1, node[i].lchild = &node[node_num]; 57 else node[i].lchild = &node[l], ++in_deg[l]; 58 if( r == -1 ) node[++node_num].type = 1, node[i].rchild = &node[node_num]; 59 else node[i].rchild = &node[r], ++in_deg[r]; 60 } 61 for(int i = 1; i <= n; ++i) if( in_deg[i] == 0 ) p_root = &node[i]; 62 p_root->deep = 1, Set_deep(p_root); 63 for(int i = 1; i <= node_num; ++i) if( node[i].type ) { 64 maxx = max(maxx, node[i].deep), minn = min(minn, node[i].deep); 65 } 66 if( maxx - minn > 1 ) puts("-1"); 67 else Deep_fs(p_root), printf("%d\n", ans == -1 ? ans : p_root->cnt); 68 69 fclose(stdin), fclose(stdout); 70 return 0; 71 }
—— “从你慷慨的手里所付予的,我都接受。我别无所求。”
“是了,是了,我懂得你,谦卑的乞丐,你是乞求一个人的一切所有。”