POJ 2567 Code the Tree & POJ 2568 Decode the Tree Prufer序列

题目大意:2567是给出一棵树,让你求出它的Prufer序列。2568时给出一个Prufer序列,求出这个树。

思路:首先要知道Prufer序列。对于任意一个无根树,每次去掉一个编号最小的叶子节点,并保存这个节点所连接的节点所得到的序列就是这棵树的Prufer序列。这个序列有十分优雅的性质,它能与无根树一一对应。因此,两个标号一样的无根树得到的Prufer序列也一定是一样的。此外,设一个节点的度数是d[i],那么他会在Prufer序列中出现d[i] - 1次。

2567:记录每一个节点的度,按照Prufer序列的定义,最后输出队列中剩余的元素。

2568:由Prufer序列能够求出每个点的度,把度数为1的点加入到队列中去,每次找一个队列中编号最小的,与当前Prufer序列中的数字连一条边,然后减少相应的度数。

CODE(2567):

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 110
using namespace std;

priority_queue<int,vector<int>,greater<int> > q;

int points;
int degree[MAX];
int head[MAX],total;
int next[MAX << 1],aim[MAX << 1];

int stack[MAX],top;
bool v[MAX];

inline void Initialize()
{
	points = total = top = 0;
	memset(degree,0,sizeof(degree));
	memset(v,false,sizeof(v));
	memset(head,0,sizeof(head));
}

inline void Add(int x,int y)
{
	next[++total] = head[x];
	aim[total] = y;
	head[x] = total;
}

inline char GetChar()
{
	char c;
	do c = getchar(); while(c == ' ' || c == '\n' || c == '\r');
	return c;
}

inline void TopSort()
{
	for(int i = 1; i <= points; ++i)
		if(degree[i] == 1)
			q.push(i),v[i] = true;
	for(int i = 1; i <= points - 2; ++i) {
		int x = q.top(); q.pop();
		for(int j = head[x]; j; j = next[j]) {
			if(v[aim[j]])	continue;
			--degree[aim[j]];
			printf("%d ",aim[j]);
			if(degree[aim[j]] == 1) {
				v[aim[j]] = true;
				q.push(aim[j]);
			}
		}
	}
	q.pop();
	printf("%d\n",q.top());
	q.pop();
}

int main()
{
	char c;
	while(GetChar() != EOF) {
		Initialize();
		scanf("%d",&stack[++top]);
		points = stack[top];
		while(top) {
	 		c = GetChar();
			if(c == '(') {
				int temp;
				scanf("%d",&temp);
				points = max(points,temp);
				Add(stack[top],temp);
				Add(temp,stack[top]);
				++degree[stack[top]];
				++degree[temp];
				stack[++top] = temp;
			}
			else	top--;
		}
		if(points == 1) {
			puts("");
			continue;
		}
		TopSort();
	}
	return 0;
}

CODE(2568):

#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 1010
using namespace std;

char s[MAX];
int src[MAX],cnt;
int degree[MAX];
int head[MAX],total;
int next[MAX],aim[MAX];
int points;

inline void Initialize()
{
	total = cnt = points = 0;
	memset(degree,0,sizeof(degree));
	memset(head,0,sizeof(head));
}

inline void Add(int x,int y)
{
	next[++total] = head[x];
	aim[total] = y;
	head[x] = total;
}

inline void Decode()
{
	static priority_queue<int,vector<int>,greater<int> > q;
	while(!q.empty())	q.pop();
	for(int i = 1; i <= points; ++i)
		if(!degree[i])	q.push(i);
	for(int i = 1; i <= cnt; ++i) {
		int x = src[i];
		int y = q.top(); q.pop();
		Add(x,y); Add(y,x);
		if(!--degree[x])	q.push(x);
	}
	//int x = q.top(); q.pop();
	//int y = q.top(); q.pop();
	//Add(x,y),Add(y,x);
}

inline void OutPut(int x,int last)
{
	if(x != 1)	putchar(' ');
	putchar('(');
	printf("%d",x);
	for(int i = head[x]; i; i = next[i]) {
		if(aim[i] == last)	continue;
		OutPut(aim[i],x);
	}
	putchar(')');
}

int main()
{
	while(gets(s) != NULL) {
		Initialize();
		char *p = s;
		while(*p != '\0') {
			sscanf(p,"%d",&src[++cnt]);
			points = max(points,src[cnt]);
			++p,++p;
			if(src[cnt] > 9)	++p;
		}
		memset(s,'\0',sizeof(s));
		for(int i = 1; i <= cnt; ++i)
			++degree[src[i]];
		Decode();
		OutPut(1,0);
		puts("");
	}
	return 0;
}
时间: 2024-10-13 16:03:44

POJ 2567 Code the Tree & POJ 2568 Decode the Tree Prufer序列的相关文章

POJ 2567 Code the Tree &amp;amp; POJ 2568 Decode the Tree Prufer序列

题目大意:2567是给出一棵树,让你求出它的Prufer序列.2568时给出一个Prufer序列,求出这个树. 思路:首先要知道Prufer序列.对于随意一个无根树,每次去掉一个编号最小的叶子节点,并保存这个节点所连接的节点所得到的序列就是这棵树的Prufer序列. 这个序列有十分优雅的性质.它能与无根树一一相应.因此.两个标号一样的无根树得到的Prufer序列也一定是一样的. 此外,设一个节点的度数是d[i],那么他会在Prufer序列中出现d[i] - 1次. 2567:记录每个节点的度.依

poj 2567 Code the Tree 河南第七届省赛

Code the Tree Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2350   Accepted: 906 Description A tree (i.e. a connected graph without cycles) with vertices numbered by the integers 1, 2, ..., n is given. The "Prufer" code of such a

POJ - 1780 Code (欧拉回路+手写DFS)

Description KEY Inc., the leading company in security hardware, has developed a new kind of safe. To unlock it, you don't need a key but you are required to enter the correct n-digit code on a keypad (as if this were something new!). There are severa

POJ 1850 Code 数位DP

据说又是一道组合数学题,数学不好的我只想出的DP写法 注意如果输入不合法要输出0 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdli

POJ 1780 Code 欧拉回路+手写栈DFS

和西安邀请赛那道题题目差不多,现在终于会手写栈了,自己琢磨了好久,真是感动TAT #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdli

POJ 1780 Code

记录欧拉路径. 题意很难懂.英语渣,翻译半天不得要领.看PDF的中文才知道题意. 题意:给一个 N (1<=N<=6)找出字典序最短的所有数字组合都出现的序列. 给出了N=2 的例子.就拿这个说明,太长就说前面的. 00102030405060708091121314151617181922324252627282933435363738394454647484955657585966768697787988990 00 出现了,01出现,然后 10,02,20,03,30,04,40,05,

Apple Tree POJ - 2486

Apple Tree POJ - 2486 题目大意:一棵点带权有根树,根节点为1.从根节点出发,走k步,求能收集的最大权值和. 树形dp.复杂度可能是O(玄学),不会超过$O(nk^2)$.(反正这题不卡这个,考思想)参考 ans[i][j][0]表示i点以下共走j步,不回来,可能收集到最大的权值ans[i][j][1]表示i点以下共走j步,回来,可能收集到最大的权值 比较复杂的是,每个节点(以下称当前节点)从其子节点转移的时候,需要用一个背包: t[i][j][0]表示当前节点的前i个子节点

Tree POJ - 1741

Tree POJ - 1741 shu de dian fen zhi 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 1e5 + 10; 7 const int inf = 0x3f3f3f3f; 8 int n, k; 9 int rt, snode

POJ 3368 线段树,给定区间求连续不降序列的在该区间内出现最多的数

Frequent values Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13771   Accepted: 5045 Description You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several queries cons