ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Uva1667NetworkMess——建树

2019-06-22 20:53:25  阅读:350  来源: 互联网

标签:fa int leaves 建树 ++ 节点 Uva1667NetworkMess deg


题意:

有一颗n个叶子的无权树,输入两两叶子的距离,恢复出这棵树并输出每个非叶子节点的度数。

思路:

参考:https://blog.csdn.net/zju2016/article/details/78450509
无根树,现将一个叶子节点作为根。逐个探测剩下的叶子节点,并在这个过程中不断增加内部节点以满足其距离要求,最终建树完成。
在这里插入图片描述
内部节点 j 的选择:
逐步测试是否能够找到某个内部的节点,使得该内部节点到所有的已经加入的外部节点的距离与待加入的外部节点的距离之差(tmp)相等,如果找到,就保存差值,逐步扩展并且计算扩展的点到已加入的外部节点的距离,计算其度数。
在这里插入图片描述

#include <cstdio>
#include <cstring>
#include <algorithm>
#define fi first
#define se second
#define pii pair<int,int>
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long LL;
const int maxn = 2000+5;
int n, idx, dis[maxn][maxn], a[55][55], deg[maxn], id[55];

void Build(){
	id[1] = ++idx; dis[1][1] = 0;
	for(int i = 2; i <= n; ++i){
		int u, last, tmp;
		for(int j = 1; j <= idx; ++j){
			tmp = a[i][1] - dis[j][1];
			int fg = 0;
			for(int k = 2; k < i; ++k) if(a[i][k] - dis[j][id[k]] != tmp){fg = 1; break;} 
			if(!fg){last = j; break;}
		}
		for(int j = 1; j <= tmp; ++j,last = u){
			deg[u = ++idx] = 0; dis[u][u] = 0;
			++deg[last]; ++deg[u];
			for(int k = 1; k < idx; ++k) dis[u][k] = dis[k][u] = dis[k][last] + 1;
		}
		id[i] = idx;
		printf("idx = %d, ",idx);
	}puts("");
}

int main()
{
	freopen("in.txt","r",stdin);
	while(scanf("%d",&n) == 1&&n){
		for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) scanf("%d",&a[i][j]);
		idx = 0; memset(deg, 0, sizeof(deg));
		
		Build();
		
		sort(deg+1, deg+idx+1);
		for(int i = 1; i <= idx; ++i){
			if(deg[i] == 1) continue;
			printf("%d",deg[i]);
			if(i != idx) printf(" ");
		} 
		printf("\n");
	}
	return 0;
}

书上的思路是递归建树:

#include <cstdio>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
#define fi first
#define se second
#define pii pair<int,int>
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long LL;
const int maxn = 50+5;
const int maxsize = 2000+5;

vector<int> M[maxn];

// 节点.nodes存的是以它为根的子树包含的叶子节点 
struct Node{ vector<Node*> nodes; } Pool[maxsize];
typedef Node* PNode;
int cnt = 0;
PNode CreateNew(){ return &Pool[cnt++]; }
void Dispose(){ for(int i = 0; i < maxsize; ++i) Pool[i].nodes.clear(); }

// 并查集 
int fa[maxn];
int find_fa(int u){ return u == fa[u]? u : fa[u] = find_fa(fa[u]); }

// 叶子节点, 根到各叶子节点的距离,根节点指针,父节点指针,度 
void BuildTree(const vector<int>& leaves, vector<int>& dis, PNode root, PNode pa, vector<int>& deg){
	// 初始化并查集 
	memset(fa, 0, sizeof(fa)); 
	for(int i = 0; i < leaves.size(); ++i) fa[leaves[i]] = leaves[i];
	
	int isLeaf[maxn]; 		// 直接在root下的叶子
	memset(isLeaf, 0, sizeof(isLeaf));
	
	// 遍历叶子 
	for(int i = 0; i < leaves.size(); ++i){
		int li = leaves[i];
		if(dis[li] == 1){
			isLeaf[li] = 1;
			root->nodes.push_back(CreateNew());		// 制造一个节点(不包含叶节点),便于后面计数 
			continue;
		}
		for(int j = i+1; j < leaves.size(); ++j){
			int ri = leaves[j];
			// 在同一个子树下, 归为一类 
			if(dis[li] + dis[ri] > M[li][ri]) fa[ri] = li;	
		}
	}
	for(int i = 0; i < leaves.size(); ++i) --dis[leaves[i]];	// 新的根到叶节点的距离
	map<int, vector<int> > subTrees;		// 每一个子树 
	for(int i = 0; i < leaves.size(); ++i){
		int x = leaves[i];
		if(0 == isLeaf[x]) subTrees[find_fa(x)].push_back(x);
	}
	
	// 递归处理每一个子树
	for(map<int, vector<int> >::iterator it = subTrees.begin(); it != subTrees.end(); ++it){
		root->nodes.push_back(CreateNew());		// 新的内部节点
		BuildTree(it->se, dis, root->nodes.back(), root, deg);
	} 
	
	if(pa&&!root->nodes.empty()) deg.push_back(root->nodes.size() + 1);
	
}

int main()
{
	freopen("in.txt","r",stdin);
	int n;
	while(scanf("%d",&n) == 1&&n){
		cnt = 0;
		for(int i = 0; i < n; ++i){
			M[i].clear();
			for(int j = 0; j < n; ++j){
				int a; scanf("%d",&a);
				M[i].push_back(a);
			}
		}
		vector<int> leaves, dis(M[0].begin(), M[0].end()), deg;
		for(int i = 1; i < n; ++i) leaves.push_back(i);
		
		BuildTree(leaves, dis, CreateNew(), NULL, deg);
		
		sort(deg.begin(), deg.end());
		for(int i = 0; i < deg.size() - 1; ++i) printf("%d ",deg[i]);
		printf("%d\n", deg[deg.size()-1]);
		Dispose();
	}
	return 0;
}


标签:fa,int,leaves,建树,++,节点,Uva1667NetworkMess,deg
来源: https://blog.csdn.net/CY05627/article/details/93361423

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有