• 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] == '' || 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。

  • 相关阅读:
    从缓冲上看阻塞与非阻塞socket在发送接收上的区别
    关于TCP封包、粘包、半包
    CURL 和LIBCURL C++代码 上传本地文件,好不容易碰到了这种折腾我几天的代码
    Spring boot 搭配 JPA 生成表注释 和 字段注释
    Spring Data JPA 中常用注解
    SpringBoot Data JPA 关联表查询的方法
    Spring boot data JPA数据库映射关系 : @OneToOne,@OneToMany,@ManyToMany
    Spring Boot Jpa 表名小写转大写
    SpringBoot入门系列~Spring-Data-JPA自动建表
    使用Spring-Session共享使用Session
  • 原文地址:https://www.cnblogs.com/pengzhen/p/4375827.html
Copyright © 2020-2023  润新知