【转】ACM 2567 -- 树的Prufer编码
本文介绍北京大学ACM网站2567号题目的解法。介绍部分基本翻译自网站上的题目介绍。
(1 (2 (3)))
(6 (1 (4)) (2 (3) (5)))
2 3
2 1 6 2 6
| 1 2 #include 3 #include 4 #include 5 6 #define END 0 // 结束 7 #define L_BRACKET 1 // 左括号 8 #define R_BRACKET 2 // 右括号 9 #define NUMBER 4 // 数 10 11 typedef struct _node 12 { 13 int value; // 节点值 14 int childs; // 子节点数 15 struct _node *parent; // 父节点 16 struct _node *first_child; // 第一个孩子节点 17 struct _node *sibling; // 下一个兄弟节点 18 }NODE; 19 20 typedef struct _token 21 { 22 int type; // 标记类型(左、右括号,数) 23 int value; // 值(仅当类型为数时有效) 24 }TOKEN; 25 26 typedef void (*FUNC)(NODE *); 27 static NODE *pSmallest = 0;// 指向最小的叶子节点 28 29 34 char *GetNextToken(char *input,TOKEN *pToken) 35 { 36 char *p,ch; 37 int value; 38 39 pToken->type = END; 40 41 p = input; 42 while ((ch = *p) && ch != '(' && ch != ')' && !isdigit(ch)) 43 p++; 44 switch(ch) 45 { 46 case '(': pToken->type = L_BRACKET; p++; break; 47 case ')': pToken->type = R_BRACKET; p++; break; 48 default: 49 50 if (isdigit(ch)) 51 { 52 value = 0; 53 while ((ch = *p) && isdigit(ch)) 54 { 55 value = 10 * value + (ch - '0'); 56 p++; 57 } 58 pToken->type = NUMBER; 59 pToken->value = value; 60 } 61 break; 62 } 63 64 return (*p == '\0' ? 0 : p); 65 } 66 67 71 NODE *BuildTree(char *input) 72 { 73 char *p; 74 TOKEN token; 75 NODE *pCur,*pNew,*pRoot,*pLast; 76 77 p = input; pCur = pLast = pRoot = 0; 78 do 79 { 80 p = GetNextToken(p,&token); 81 switch(token.type) 82 { 83 case L_BRACKET: 84 break; 85 case R_BRACKET: 86 87 pLast = pCur; 88 if (0 != pCur) 89 pCur = pCur->parent; 90 break; 91 case NUMBER: 92 pNew = (NODE *)malloc(sizeof(NODE)); 93 memset(pNew,0,sizeof(NODE)); 94 pNew->value = token.value; 95 96 pNew->parent = pCur; 97 if (0 != pLast) 98 { 99 pLast->sibling = pNew; 100 pLast = pNew; 101 } 102 if (0 != pCur) 103 { 104 if (0 == pCur->childs++) 105 pCur->first_child = pNew; 106 } 107 else pRoot = pNew; 108 109 p = GetNextToken(p,&token); 110 if (token.type == L_BRACKET) 111 { 112 pCur = pNew; 113 pLast = 0; 114 } 115 else if (token.type == R_BRACKET) 116 pLast = pNew; 117 break; 118 } 119 }while (0 != p); 120 return pRoot; 121 } 122 123 127 void TravelTree(NODE *pRoot,FUNC func) 128 { 129 NODE *pCur; 130 if (0 == pRoot) return; 131 (*func)(pRoot); 132 pCur = pRoot->first_child; 133 while (pCur) 134 { 135 TravelTree(pCur,func); 136 pCur = pCur->sibling; 137 } 138 } 139 140 141 int IsLeafNode(NODE *pNode) 142 { 143 return (0 != pNode && (0 == pNode->childs && 0 != pNode->parent) 144 || (1 == pNode->childs && 0 == pNode->parent)); 145 } 146 147 148 void LeafValueCompare(NODE *pNode) 149 { 150 if (IsLeafNode(pNode)) 151 if (0 == pSmallest) pSmallest = pNode; 152 else if (pNode->value < pSmallest->value) 153 pSmallest = pNode; 154 } 155 156 161 NODE *ReleaseLeafNode(NODE *pRoot,NODE *pNode) 162 { 163 NODE *pParent,*pSibling; 164 if (0 == pNode->childs) 165 { 166 pParent = pNode->parent; 167 if (pParent) 168 { 169 pSibling = pParent->first_child; 170 if (pNode == pSibling) 171 pParent->first_child = pNode->sibling; 172 else 173 { 174 while (pSibling && pSibling->sibling != pNode) 175 pSibling = pSibling->sibling; 176 if (pSibling) 177 pSibling->sibling = pNode->sibling; 178 } 179 pParent->childs--; 180 } 181 free(pNode); 182 } 183 else 184 { 185 pRoot = pNode->first_child; 186 pRoot->parent = 0; 187 free(pNode); 188 } 189 return pRoot; 190 } 191 192 void ReleaseTree(NODE *pRoot) 193 { 194 NODE *pCur,*pNext; 195 if (pRoot) 196 { 197 pCur = pRoot->first_child; 198 while (pCur) 199 { 200 pNext = pCur->sibling; 201 ReleaseTree(pCur); 202 pCur = pNext; 203 } 204 free(pRoot); 205 } 206 } 207 208 int main(int argc,char *argv[]) 209 { 210 NODE *pRoot; 211 char line[250]; 212 int n; 213 while (!feof(stdin)) 214 { 215 line[0] = '\0'; 216 gets(line); 217 pRoot = BuildTree(line); 218 n = 0; 219 while (pRoot && pRoot->childs != 0) 220 { 221 pSmallest = 0; 222 TravelTree(pRoot,LeafValueCompare); // 遍历树 223 if (0 == pSmallest->childs) 224 printf(n++ ? " %d" : "%d",pSmallest->parent->value); 225 else 226 printf(n++ ? " %d" : "%d",pSmallest->first_child->value); 227 pRoot = ReleaseLeafNode(pRoot,pSmallest); 228 } 229 if (0 != pRoot) 230 { 231 printf("\n"); 232 ReleaseTree(pRoot); 233 } 234 } 235 return 0; 236 } 237 |
【转】ACM 2567 -- 树的Prufer编码的更多相关文章
- BZOJ1005--[HNOI2008]明明的烦恼(树的prufer编码)
1005: [HNOI2008]明明的烦恼 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 5768 Solved: 2253[Submit][Stat ...
- 树的Prufer 编码和最小生成树计数
Prufer数列 Prufer数列是无根树的一种数列.在组合数学中,Prufer数列由有一个对于顶点标过号的树转化来的数列,点数为n的树转化来的Prufer数列长度为n-2.它可以通过简单的迭代方 ...
- 树的prufer编码
prufer是无根树的一种编码方式,一棵无根树和一个prufer编码唯一对应,也就是一棵树有唯一的prufer编码,而一个prufer编码对应一棵唯一的树. 第一部分:树编码成prufer序列. 树编 ...
- 【51NOD1806】wangyurzee的树(Prufer编码,容斥原理,组合计数)
题意:有n个点和m条限制,每条限制限制了一个点的度数不能为某个数. 求合法的树的个数模10^9+7 n<=10^6 m<=17 思路:WYZ作业 首先m<=17显然是2^m容斥 枚举 ...
- 【Foreign】树 [prufer编码][DP]
树 Time Limit: 10 Sec Memory Limit: 256 MB Description Input Output Sample Input 3 2 2 1 Sample Outp ...
- 【转】prufer编码
既然有人提到了,就顺便学习一下吧,来源:http://greatkongxin.blog.163.com/blog/static/170097125201172483025666/ 一个含有n个点的完 ...
- 「模拟赛20180406」膜树 prufer编码+概率
题目描述 给定一个完全图,保证\(w_{u,v}=w_{v,u}\)且\(w_{u,u}=0\),等概率选取一个随机生成树,对于每一对\((u,v)\),求\(dis(u,v)\)的期望值对\(998 ...
- Luogu2290 [HNOI2004]树的计数 (组合计数,prufer编码)
这不prufer编码吗,防爆long long就行了啊 #include <iostream> #include <cstdio> #include <cstring&g ...
- Codeforces 1109D. Sasha and Interesting Fact from Graph Theory 排列组合,Prufer编码
原文链接https://www.cnblogs.com/zhouzhendong/p/CF1109D.html 题意 所有边权都是 [1,m] 中的整数的所有 n 个点的树中,点 a 到点 b 的距离 ...
随机推荐
- Jmeter常用的逻辑控制器
一.ForEach控制器 作用:ForEach Controlle一般和用户自定义变量(User Defined Variables)一起使用,其在用户自定义变量中读取一系列相关的变量.每一个线程下执 ...
- sort 排序 自定义排序算法的使用
// struct sort_by_pt// {// bool operator()(const std::pair<CString, AcGePoint3d> a, const std: ...
- VC++代码转换为QT代码问题总结
一边开发一边总结...... QQ937113547
- java中的数学函数Math方法记录
1,三角函数与属性Math.sin() -- 返回数字的正弦值Math.cos() -- 返回数字的余弦值Math.tan() -- 返回数字的正切值Math.asin() -- 返回数字的反正弦值M ...
- Linux常用命令——目录处理命令
1.建立目录:mkdir mkdir -p [目录名] -p 递归创建 命令英文原意:make directories 实例: [root@localhost ~]# ls anaconda-ks.c ...
- Luogu P4316 绿豆蛙的归宿
P4316 绿豆蛙的归宿 题意翻译 「Poetize3」 题目背景 随着新版百度空间的上线,Blog宠物绿豆蛙完成了它的使命,去寻找它新的归宿. 题目描述 给出一个有向无环图,起点为1终点为N,每条边 ...
- HDU - 2050 - 折线分割平面(数学 + dp)
题意: 我们看到过很多直线分割平面的题目,今天的这个题目稍微有些变化,我们要求的是n条折线分割平面的最大数目.比如,一条折线可以将平面分成两部分,两条折线最多可以将平面分成7部分 思路: 记住结论.. ...
- 用python写了一个猜年龄小游戏
写一个猜年龄游戏: 需要实现用户登录的功能 初始用户登录信息为 {'hades': '13579','nick': '123','ruixing': 'a1','fanping': 'b2'} 登录时 ...
- led1,1s取反,led2计数10次取反
1 //利用定时器0 1s,led1取反,利用计数器1,跳10,取反 #include<reg52.h> #define uchar unsigned char #define uint ...
- Linux学习总结(19)——Linux中文本编辑器vim特殊使用方法
1. vim比对功能 在linux的环境下 用于观察两个文件的一致性的时候我们一般用diff这个命令来比对,但是这个命令不能你特别详细的比对出 具体的位置或者行对比.这里就用到了vim的对比功能 vi ...