http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1097
题目大意:
树(即无环图)的顶点,用整数1,2……,n编号。Prufer码是按如下步骤构造的树:找到编号最小的叶节点,将该叶节点及其相连的那条变,从图中删除的同时,记下与它相连的那个结点的编号。重复上面的步骤,知道剩下最后一个结点(这个数就是n)。写下来的n-1个数的序列,就是该树的Prufer码。
编程任务:根据输入的树计算该树的Prufer码。
树的语法规则如体重描述
就是说,树的周围有括号。第一个树是根节点的编号,后面更有任意个子树(也可能没有),中间有一个空格。
算法分析:
1、数据结构
需要将每个结点的相邻节点建立对应关系,使用vector()和set()很容易实现,操作也比较方便 :vector<set<int> >
2、实现Prufer编码
使用优先队列处理,对于一个结点,当只有一个结点与其相邻时,就是叶子节点,首先将所有叶子结点放入优先队列中,选出编号最小的叶节点,输入其相邻结点,同时删除次叶节点,并在处理过程中将成为叶节点的结点放入优先队列中。
Priority_queue<int,vector<int> ,greater<int> >leafs;
3、对于本题主要在于建立各个结点间的对应关系,我采用的是非递归的方法建立,也可用递归实现
View Code
#include<iostream> #include<stack> #include<vector> #include<queue> #include<set> #include<cstring> #include<cstdio> using namespace std; char str[300]; void init(vector<set<int> > &adj) { int x,y,n,len=strlen(str),pos=0; stack<int>num; while(pos<len-1) { if(str[pos]=='(') //左括号,标号进栈 { sscanf(str+pos+1,"%d%n",&x,&n); pos+=n+1; //pos移动到数字后面一位 num.push(x); } else if(str[pos]==')') //右括号,读取栈顶两个元素, { y = num.top(); num.pop(); x = num.top(); adj[x].insert(y); //结点的相邻是对称的 adj[y].insert(x); pos++; //pos移位 } else if(str[pos]==' ') pos++; //空格,向后移动 } } int main() { int x,y,i,sum; while(gets(str)) { vector<set<int> >adj(100,set<int>()); x = y = 1; init(adj); priority_queue<int,vector<int>,greater<int> >leafs; sum=0; for(i=1;adj[i].size();i++) { sum++; //统计结点个数 if(adj[i].size()==1) //叶子节点进入优先队列 leafs.push(i); } for(i=1;i<sum;i++) //处理优先队列 { x = leafs.top(); leafs.pop(); y = *(adj[x].begin()); adj[x].erase(y); //删除关系 adj[y].erase(x); if(adj[y].size()==1) //如果y也成为叶子节点,进入优先队列 leafs.push(y); if(i>1) cout<<' '; cout<<y; // } cout<<endl; } return 0; }
View Code
#include <iostream> #include <queue> #include <set> #include <vector> using namespace std; void parse (vector<set<int> > &adj, unsigned int p = 0) { //采用递归来进行数据与结点编号的转换 unsigned int x; cin >> ws >> x; //cin>>ws 忽略空格,读取编号 if (p) //相邻对称,p为真,表示前面读取的是结点编号 { adj[p].insert (x); adj[x].insert (p); } while (true) { char ch; cin >> ws >> ch; //读取括号 if (ch == ')') break; //如果是‘)’,递归返回 parse (adj, x); //否则是‘(’,递归调用 } return; } int main () { char ch; while (cin >> ws >> ch) { vector<set<int> > adj (1024, set<int>()); parse (adj); priority_queue< int, vector<int>, greater<int> > leafs; int n = 0; for (unsigned int i=0; i<adj.size(); i++) if (adj[i].size()) { n++; if (adj[i].size() == 1) leafs.push (i); } for (int k=1; k<n; k++) { unsigned int x = leafs.top(); leafs.pop(); unsigned int p = *(adj[x].begin()); if (k > 1) cout << " "; cout << p; adj[p].erase(x); if (adj[p].size() == 1) leafs.push (p); } cout << endl; } return 0; }