1. 程式人生 > >[APIO2007] 風鈴

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

 

 —— “從你慷慨的手裡所付予的,我都接受。我別無所求。”
    “是了,是了,我懂得你,謙卑的乞丐,你是乞求一個人的一切所有。”