【转】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 的距离 ...
随机推荐
- 安卓app测试之cpu监控
安卓app测试之cpu监控,如何获取监控的cpu数据呢? 一.通过Dumpsys 来取值 1.adb shell dumpsys cpuinfo 二.top 1.top -d 1|grep packa ...
- day15-模块的基础及导入
目录 模块 什么是模块 使用模块 import 循环导入问题 解决方案一 解决方案二 模块的搜索路径 Python文件的两种用途 包 导入包内包 导入包内包的模块 绝对导入与相对导入 绝对导入 相对导 ...
- CAD设置系统变量(com接口VB语言)
主要用到函数说明: MxDrawXCustomFunction::Mx_SetSysVar 设置系统变量.详细说明如下: 参数 说明 CString sVarName 系统变量名 Value 需要设置 ...
- 梦想CAD控件COM接口搜索图面上的文字
点击此处下载演示实例 主要用到函数说明: _DMxDrawX::NewSelectionSet 实例化一个构造选择集进行过滤,该类封装了选择集及其处理函数. _DMxDrawX::NewResbuf ...
- 11Java Server Pages 动作
Java Server Pages 动作 JSP标准动作 分类 JSP标准动作 存取JavaBean相关 <jsp:useBean> <jsp:setProperty> < ...
- Java运算符法则
JAVA运算符法则 运算符是一种特殊的符号,用于表示数据的运算,赋值和比较等: 算术运算符 正号+,负号-,加+,减-,乘*,除/,余或取模%,自增++,自减--,字符串相加+ 正号负号运算符代表运算 ...
- 【Redis】二、Redis高级特性
(三) Redis高级特性 前面我们介绍了Redis的五种基本的数据类型,灵活运用这五种数据类型是使用Redis的基础,除此之外,Redis还有一些特性,掌握这些特性能对Redis有进一步的了解, ...
- python多进程和多线程编程
17 多线程和多进程并发 The modules described in this chapter provide support for concurrent execution of code. ...
- 洛谷——P2709 小B的询问
P2709 小B的询问 莫队算法,弄两个指针乱搞即可 这应该是基础莫队了吧 $x^2$可以拆成$((x-1)+1)^2$,也就是$(x-1)^2+1^2+2\times (x-1)$,那么如果一个数字 ...
- docker-ce安装官翻
参考http://www.cnblogs.com/maple42/p/5868846.htmlhttp://blog.csdn.net/lizehua123/article/details/50601 ...