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。

时间: 2024-10-05 20:38:14

zoj 1097 普吕弗序列的相关文章

POJ 2575 &amp;&amp; ZOJ 1879 Jolly Jumper(整数序列)

链接:click here 题意:对于一个包含n>0个元素的整数序列,如果序列中相邻元素之差的绝对值取边1到n-1的所有值,那么这个序列就叫做Jolly Jumper序列, 思路:水题模拟~~,不过注意*,因为不小心,wrong了几遍. 代码: #include <stdio.h> #include <string.h> #include <iostream> #include <vector> #include <iterator> #i

爱情随想.苏利&#183;普吕多姆

◆所有的情人都不是诗人,远远不是,谢天谢地!然而有个东西所有的情人都用诗人的目光来看,那就是所爱的对象. ◆我欣赏“对象”这个词.是的,所爱的女人是时间和疾病毁坏的对象,她像许多衰老的东西一样由此失去所有的魅力,因为爱情说穿了是对外貌的一种崇拜.男人们自相矛盾地指责打扮和化妆这种与岁月可怜的斗争!首饰和脂粉是女人耻辱我们的东西. ◆极其妄自尊大才会相信自己被人爱,可要不再相信自己被人爱,那得非常不幸才行. 情人似乎想让他人高兴甚于自己享乐,但他还是利己主义者,因为他想让人高兴的目的是为了自己享乐

Code the Tree ZOJ - 1097

传送门:https://vjudge.net/problem/ZOJ-1097 解题思路: 主要是找到每一节点的相邻节点,然后后面的用优先队列就行了. #include <cstdio> #include <queue> #include <vector> #include <set> #include <iostream> using namespace std; void parse(vector<set<int> >

劫富济贫

p { margin-bottom: 0.25cm; direction: ltr; line-height: 120%; text-align: justify } p.western { font-family: "Calibri", serif; font-size: 10pt } p.cjk { font-size: 10pt } p.ctl { font-family: "Calibri"; font-size: 10pt } [问题描述] 吕弗·普自小从

有哪些电影一定要趁年轻看? - 风之影的回答 - 知乎

body { font-family: Microsoft YaHei UI,"Microsoft YaHei", Georgia,Helvetica,Arial,sans-serif,宋体, PMingLiU,serif; font-size: 10.5pt; line-height: 1.5; } html, body { } h1 { font-size:1.5em; font-weight:bold; } h2 { font-size:1.4em; font-weight:bo

诺贝尔作品收藏

1.1901年作品<孤独与深思>获诺贝尔文学奖.苏利·普吕多姆(1839-1907)法国诗人. 获奖理由:“是高尚的理想.完美的艺术和罕有的心灵与智慧的实证" 2.1902年作品<罗马风云>获诺贝尔文学奖.特奥多尔·蒙森(1817-1903)德国历史学家. 获奖理由:“今世最伟大的纂史巨匠,此点于其巨著<罗马史>中表露无疑” 3.1903年作品<挑战的手套>获诺贝尔文学奖.比昂斯滕·比昂松(1832-1910)挪威戏剧家.诗人.小说家. 获奖理由:

认识数学各个分支

数论 人类从学会计数开始就一直和自然数打交道了,后来由于实践的需要,数的概念进一步扩充,自然数被叫做正整数,而把它们的相反数叫做负整数,介于正整数和负整数中间的中性数叫做0.它们和起来叫做整数. 对于整数可以施行加.减.乘.除四种运算,叫做四则运算.其中加法.减法和乘法这三种运算,在整数范围内可以毫无阻碍地进行.也就是说,任意两个或两个以上的整数相加.相减.相乘的时候,它们的和.差.积仍然是一个整数.但整数之间的除法在整数范围内并不一定能够无阻碍地进行. 人们在对整数进行运算的应用和研究中,逐步

转载网文:年轻人为什么要去大城市

年轻人为什么要去大城市 在大城市打拼还是回小城市过相对安逸的生活,这是一个近年来始终争论不休的问题.可是,它真的是一个大问题吗? 几年前的一天,我去某地开一个无聊的会.入会场前,我顺手在副驾座位上拿了本杂志,其中有一篇刘大任的<柏克莱那几年>.幸有此文,让我不至于选择早退. 上世纪六十年代,刘大任从台湾去美国求学,恰在柏克莱遭遇了自由言论运动风潮.最终,他与许多同龄人一样,成为了“乌托邦的寻找者”. 尽管刘大任的左翼思维与我并不相投,但不妨碍我被其文字打动.这位如今已垂垂老矣的小说家写道:“也

張國榮鮮為人知的52個電影秘密

1,<色情男女>主角原型是谁? 仔细看的话,会发现<色情男女>刘青云饰演的“尔东升”有一张被偷怕和同性朋友的亲密照 <色情男女>说的是满怀理想的年轻导演阿星(张国荣饰)由于处境艰难沦落执导三级片,他接受现实后,便决定拍出有质量不低俗三级片故事.一直来,这部电影都被观众认为是导演尔冬升在夫子自道,事实上,故事原型并不是他,尔冬升接受访问时都表示另有其人,也常常出于好意不愿说出对方名字. 毕竟拍三级片不是什么值得显耀的事.化名拍戏更是见怪不怪.电影里有一段情节,一导演得意的