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。

原文地址:https://www.cnblogs.com/pengzhen/p/4375827.html