zoj 1097 普吕弗序列
题目大意:输入一颗无根树的括号序列,求这棵树的普吕弗序列。
分析思路:
1)普吕弗序列,可以参考维基百科,其做法是找出树中编号最小的叶子节点,并将此叶子节点及边删除,并输出其邻接的节点标号;
2)递归地构造树,可以使用list<int> 数组来表示一个“邻接表”,以存储构造的树;
3)使用优先队列来进行删除,奈何priority_queue没有迭代器访问,只能用堆排序,取最值;
代码:
#include<iostream>
#include<vector>
#include<map>
#include<queue>
#include<string>
#include<algorithm>
#include<fstream>
#include<list>
using namespace std; struct nodeAndDegree
{
int degree; //度
int nodeNumber; //结点编号
bool operator < (const nodeAndDegree& n1)const
{
return degree == n1.degree ? (nodeNumber > n1.nodeNumber) : (degree > n1.degree);
}
}; const int MAX_LEN = 55;
list<int> vGraph[MAX_LEN];
vector<int> v;
int rootNumber = 0; void dfs(int start, int end, int parent, string str)
{
if (start == end) //只有单个点
{
return;
} //放入邻接矩阵
int currentNode = 0;
for (int i = start + 1; i <= end - 1; i++)
{
if (str[i] == ' ' || str[i] == '\0' || str[i] == '(')
{
break;
}
currentNode = currentNode * 10 + (int)(str[i] - 48);
} //放入邻接矩阵
vGraph[parent].push_back(currentNode);
vGraph[currentNode].push_back(parent);
v.push_back(currentNode); int mark = 0;
int tmpStart = -1;
for (int i = start + 1; i <= end - 1; i++)
{
if (str[i] == '(')
{
mark++;
if (tmpStart == -1) tmpStart = i;
continue;
} if (str[i] == ')')
{
mark--;
if (mark == 0)
{
dfs(tmpStart, i, currentNode, str);
tmpStart = -1;
}
}
}
} void print_prufer_sequnce()
{
//首先修改根节点对应的长度
int tmp = vGraph[0].front();
vGraph[tmp].remove(0); vector<nodeAndDegree> listNodeDegree;
for (int i = 0; i < v.size(); i++)
{
nodeAndDegree *nd = new nodeAndDegree();
nd->nodeNumber = v[i];
nd->degree = vGraph[v[i]].size(); listNodeDegree.push_back(*nd);
} int n = v.size() - 1;
int index = 0; while (index < n)
{
make_heap(listNodeDegree.begin(), listNodeDegree.end());
int number = listNodeDegree[0].nodeNumber; //当前结点
int front = vGraph[number].front(); cout << front ;
if (index != n - 1)
{
cout << " ";
}
vGraph[front].remove(number);
vGraph[number].remove(front);
for (int j = 1; j < listNodeDegree.size(); j++)
{
if (listNodeDegree[j].nodeNumber == front)
{
listNodeDegree[j].degree--;
break;
}
} listNodeDegree.erase(listNodeDegree.begin()); index++;
}
} int main()
{
string s;
//fstream cin("1097.txt");
while (getline(cin, s))
{
for (int i = 0; i < MAX_LEN; i++)
{
vGraph[i].clear();
}
v.clear();
dfs(0, s.size() - 1, 0, s);
print_prufer_sequnce();
cout << endl;
}
return 0;
}
以纪念我那逝去的耗费精力的兴奋的AC。
zoj 1097 普吕弗序列的更多相关文章
- 线性时间构造普吕弗(Prüfer)序列
tree -> sequence 首先预处理数组 deg[N], deg[i]表示编号为i的节点的度数,我们每次要删除的节点肯定是 满足deg[i]=1 的编号最小节点, 首先找到所有叶子并选出 ...
- 计蒜客NOIP模拟赛(2) D2T1 劫富济贫
[问题描述] 吕弗·普自小从英国长大,受到骑士精神的影响,吕弗·普的梦想便是成为一位劫富济贫的骑士. 吕弗·普拿到了一份全国富豪的名单(不在名单上的都是穷人),上面写着所有富豪的名字以及他们的总资产, ...
- hdu 1394 zoj 1484 求旋转序列的逆序数(并归排序)
题意:给出一序列,你可以循环移动它(就是把后面的一段移动到前面),问可以移动的并产生的最小逆序数. 求逆序可以用并归排序,复杂度为O(nlogn),但是如果每移动一次就求一次的话肯定会超时,网上题解都 ...
- 无向图的完美消除序列 判断弦图 ZOJ 1015 Fish net
ZOJ1015 题意简述:给定一个无向图,判断是否存在一个长度大于3的环路,且其上没有弦(连接环上不同两点的边且不在环上). 命题等价于该图是否存在完美消除序列. 所谓完美消除序列:在 vi,v ...
- ZOJ 3963 Heap Partition set维护。给一个序列,将其划分成尽量少的序列,使每一个序列满足按照顺序构造二叉树,父母的值<=孩子的值。
Heap Partition Time Limit: Seconds Memory Limit: KB Special Judge A sequence S = {s1, s2, ..., sn} i ...
- ZOJ 3795 Grouping 求最长链序列露点拓扑
意甲冠军:特定n积分.m向边条. 该点被划分成多个集合随机的每个集合,使得2问题的关键是无法访问(集合只能容纳一个点) 问至少需要被分成几个集合. 假设没有戒指,接着这个话题正在寻求产业链最长的一个有 ...
- (队列的应用5.3.1)ZOJ 3210 A Stack or A Queue?根据进入结构的序列和离开结构的序列确定是stack还是queue)
/* * ZOJ_3210.cpp * * Created on: 2013年10月30日 * Author: Administrator */ #include <iostream> # ...
- ZOJ 2319 Beatuiful People(单调递增序列的变形)
Beautiful People Time Limit: 5 Seconds Memory Limit: 32768 KB Special Judge The most prest ...
- 弗拉特利定律:Illumina怎样缔造基因革命
蕾妮·瓦林特(Renee Valint)的女儿谢尔碧(Shelby)在2000年出生时.看起来虚弱无力,就如同一仅仅耷拉着的布娃娃.谢尔碧学着走路和说话,但学得很慢.错过了儿童发展的重要阶段.到4岁时 ...
随机推荐
- PHP+MySQL无限级分类(非递归)
要实现无限级分类,递归一般是第一个也是最容易想到的,但是递归一般被认为占用资源的方法,所以很多系统是不考虑使用递归的 本文还是通过数据库的设计,用一句sql语句实现 数据库字段大概如下: 字段 说明 ...
- bwa的使用方法
bwa的使用需要两中输入文件: Reference genome data(fasta格式 .fa, .fasta, .fna) Short reads data (fastaq格式 .f ...
- poj1753枚举
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33670 Accepted: 14713 Descr ...
- 二模 06day2
很长时间没更新有意义的题目了呢,这是一套题撒,于是乎我便开心的边刷题边发题解了撒. 第一题: interval 比较好玩的一题撒, 分分钟过了, 就是模拟贪吃蛇但是没有食物(嗯,只要你判断冲突). 整 ...
- 基于Matlab的MMSE的语音增强算法的研究
本课题隶属于学校的创新性课题研究项目.2012年就已经做完了,今天一并拿来发表. 目录: --基于谱减法的语音信号增强算法..................................... ...
- 【OpenStack】OpenStack系列1之OpenStack本地开发环境搭建&&向社区贡献代码
加入OpenStack社区 https://launchpad.net/,注册用户(597092663@qq.com/Admin@123) 修改个人信息,配置SSH keys.OpenPGP keys ...
- 2.16 最长递增子序列 LIS
[本文链接] http://www.cnblogs.com/hellogiser/p/dp-of-LIS.html [分析] 思路一:设序列为A,对序列进行排序后得到B,那么A的最长递增子序列LIS就 ...
- 25.在从1到n的正数中1出现的次数[NumberOf1Between1_N]
[题目] 输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数.例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次. [分析] 这是一道广为流传的goo ...
- Java for LeetCode 174 Dungeon Game
The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon. ...
- ORACLE清除某一字段重复的数据(选取重复数据中另一个字段时期最大值)
需求:资产维修表中同一资产可能维修完继续申请维修,这时候维修状态需要根据最近的维修时间去判断维修状态,所以同一资产ID下会出现重复的数据(维修审批通过,维修审批未通过),或者可能不出现(未申请维修), ...