SGU 134.Centroid(图心)

SGU链接

时间限制:0.25s

空间限制:4M

题意

给出一个树(节点数<=16000),一个节点的重量定义为从树中去除这个点后,新得到的所有树中节点最多的树的节点数。树的中心定义为所有节点重量最小的那几个。

要求输出给定树的树的中心的重量,以及所有的树心的编号。



Solution

首先,以任意节点为根,构造一颗具有父子节点关系的树。

使用递归即可,Fa[i]记录i的父亲节点编号。

sum[i],记录i节点以其所有儿子节点一共有多少个节点。

显然如果以1号节点为根 sum[1]=n;

再来考虑如何得到一个节点的重量。

对于根节点,它的重量是 所有 儿子节点sum[j]中的最大值。

对于根节点的儿子k呢?

它的重量是他的 所有儿子节点的sum[]和 (sum[1]-sum[k])的最大值。

那么对于k的儿子呢?

这时可以注意到计算k 的时候与根节点其他儿子已经没有关系了,需要的只是sum[i],

在计算k儿子时,把k当做根,这时sum[k]=n;

设p为k的儿子,

p的重量就是 它所有儿子的sum[]和 (sum[k]-sum[p])的最大值.

最后只要存下不同重量的节点有哪一些输出就可以了。

参考代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <vector>
#define INF 16666
using namespace std;
struct node {
	int v, ne;
} edge[INF<<2];
queue<int> ql;
int head[INF], fa[INF], pd[INF];
int sum[INF], cnt, nCnt[INF];
vector<int>  out[INF];
int n, m, ans = INF;
void added (int u, int v) {
	edge[++cnt].v = v;
	edge[cnt].ne = head[u];head[u] = cnt;
}
int Count (int x) {
	pd[x] = sum[x] = 1;
	for (int i = head[x]; i != 0; i = edge[i].ne) {
		int j = edge[i].v;
		if (!pd[j]) {
			fa[j] = x;
			sum[x] += Count (j);
		}
	}
	return sum[x];
}
void make (int x) {
	int k=0;
	if (fa[x] != 0) k = sum[fa[x]] - sum[x];
	for (int i = head[x]; i != 0; i = edge[i].ne) {
		int j = edge[i].v;
		if (j != fa[x]){
			k = max (k, sum[j]);
			if(fa[x]!=0) sum[x]=sum[fa[x]];
			make(j);
		}
	}
	if (ans >= k) {
		ans = k;
		out[k].push_back (x);
		nCnt[k]++;
	}
}
int main() {
	int x, y, c;
	scanf ("%d", &n);
	for (int i = 1; i <= n - 1; i++) {
		scanf ("%d %d", &x, &y);
		added (x, y), added (y, x);
	}
	Count (1);
	make (1);
	printf ("%d %d\n", ans, nCnt[ans]);
	sort (out[ans].begin(), out[ans].end() );
	for (int i = 0; i <= out[ans].size() - 1; i++)
		printf ("%d ", out[ans][i]);
	return 0;
}

  

SGU 134.Centroid(图心)

时间: 2024-08-24 17:48:05

SGU 134.Centroid(图心)的相关文章

SGU 134.Centroid( 树形dp )

一道入门树dp, 求一棵树的重心...我是有多无聊去写这种题...傻X题写了也没啥卵用以后还是少写好.. ---------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 16009; int sz[maxn], N; in

SGU - 134 Centroid 无根树转有根树 + 树形DP

题目大意:给出一个无向图(树),要求你删除掉其中一个点,使剩下的点构成的子树中,节点数最大的那个值达到最小 解题思路:因为给出的是一个无根树,第一个想法就是先把它转成有根树,将1当成根 设sum[i]为以i为根节点的子树有多少个节点,那么sum[1] - sum[i]就相当于是排除了i的所有子节点的另一棵子树的节点总数了 设dp[i]为去掉了i节点后的剩余节点所构成的子树的节点的最大值 那么dp[i] = max(dp[i], sum[son]) son指的是和i相连的子节点 还有另一棵子树,就

树形DP求树的重心 --SGU 134

令一个点的属性值为:去除这个点以及与这个点相连的所有边后得到的连通分量的节点数的最大值. 则树的重心定义为:一个点,这个点的属性值在所有点中是最小的. SGU 134 即要找出所有的重心,并且找出重心的属性值. 考虑用树形DP. dp[u]表示割去u点,得到的连通分支的节点数的最大值. tot[u]记录以u为根的这棵子树的节点数总和(包括根). 则用一次dfs即可预处理出这两个数组.再枚举每个点,每个点的属性值其实为max(dp[u],n-tot[u]),因为有可能最大的连通分支在u的父亲及以上

动态树

sgu 134 这题说的是寻找这个树的重心 给你一个连通的无向图,他有N 个顶点和 N-1 条边 (一棵树).现在你需要找到这棵树的重心.现在定义树的重心,树的每一个顶点有一个权值.考虑顶点k.如果从图中删除k号顶点(连带的边也一起被删除),剩下的图将只有 N-1 个顶点而且可能由多个连通分量组成.显然每一个连通分量还是一棵树.那么k号顶点的权值就是删除它以后剩下的连通分量中顶点数最多的顶点个数,删除k之后.这 N 个顶点中权值最小的就是重心. 此题要求我们求一棵树的重心. 给定一棵N个结点的树

归一化变换 Normalizing transformations

归一化变换包含两个部分,图像坐标的平移和尺度的缩放.进行归一化的变换不但能够提高处理结果的精确度,而且通过选择一个标准的坐标系预先的消除了图像尺度和坐标原点的选择对算法最终结果的影响. 归一化变换的步骤: 对点进行平移,让这些点的图心(Centroid)移到原点 进行尺度缩放,让这些点的到原点的平均距离为 数据的归一化在一些算法中是必须得,特别是对一些不太良定的问题,例如:基本矩阵的计算以及三焦张量的DLT算法. 归一化变换矩阵T的求解: 是的平均值 尺度S为

unsupervised learning: K-means 算法

k-means算法是目前最流行的,用得最多的一种clustering算法 K-means算法 如果我们想要将上图中的绿色的点分为两类,首先随机的选取两个cluster centroids(聚类中心),然后迭代(循环)地做两件事:cluster assignment和move centroids(图1) cluster assignment: 然后将训练集中的每个样本,根据是距离红色的cluster centroid近还是蓝色的cluster centroid近来进行分配cluster.(图2)

CSS3学习笔记(2)—左右跳动的红心

还在为无法表达内心澎湃的心情而着急吗?还在为制作跳动的心而烦恼吗?哈哈~~~今天我就把代码全部奉上,为你们追妹子添点贡献,下面来看最终的动态效果(事先说明一下:我用的截屏gif制作软件是绿色版的,所以gif动态图心的抖动效果会有点慢而且卡卡的,但是实际效果很棒~~~不信你可以粘贴代码看看呗) 下面把心的png图也贴出来,感兴趣的可以右键另存为试试~~~~ 其实上面的动画类似于我们小时候荡的秋千,也叫作“秋千动画”,一般用在想让用户点击这个图标的时候,不仅仅限制于表白用O(∩_∩)O,比如企业招聘

利用filter实时切换big5和gb2312,以及gb2312的简繁体

IEEE Spectrum 杂志发布了一年一度的编程语言排行榜,这也是他们发布的第四届编程语言 Top 榜. 据介绍,IEEE Spectrum 的排序是来自 10 个重要线上数据源的综合,例如 Stack Overflow.Twitter.Reddit.IEEE Xplore.GitHub.CareerBuilder 等,对 48 种语言进行排行. 与其他排行榜不同的是,IEEE Spectrum 可以让读者自己选择参数组合时的权重,得到不同的排序结果.考虑到典型的 Spectrum 读者需求

俑烟汲的诿樟透磺勒秤窗mvus

IEEE Spectrum 杂志发布了一年一度的编程语言排行榜,这也是他们发布的第四届编程语言 Top 榜. 据介绍,IEEE Spectrum 的排序是来自 10 个重要线上数据源的综合,例如 Stack Overflow.Twitter.Reddit.IEEE Xplore.GitHub.CareerBuilder 等,对 48 种语言进行排行. 与其他排行榜不同的是,IEEE Spectrum 可以让读者自己选择参数组合时的权重,得到不同的排序结果.考虑到典型的 Spectrum 读者需求