SGU 134.Centroid(图心)
时间限制: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(图心)的更多相关文章
- SGU 134.Centroid( 树形dp )
一道入门树dp, 求一棵树的重心...我是有多无聊去写这种题...傻X题写了也没啥卵用以后还是少写好.. ----------------------------------------------- ...
- SGU 134 Centroid
题意:给出一个树,每个点有一个value,value的意义是去掉这个点之后所有连通分量中点最多的那个连通分量的点数,这棵树的重心为所有点value的最小值,求重心,及重心都有谁. 解法:貌似是个树形d ...
- 树形DP求树的重心 --SGU 134
令一个点的属性值为:去除这个点以及与这个点相连的所有边后得到的连通分量的节点数的最大值. 则树的重心定义为:一个点,这个点的属性值在所有点中是最小的. SGU 134 即要找出所有的重心,并且找出重心 ...
- Centroid - SGU 134(树的搜索)
题目大意:给你一个树,树每个点都有一个值, 这个点的的值就等于所有儿子里面点最多的那个儿子,值最小的就叫做重心,求出重心,还有所有等于重心的点,按照升序输出. 分析:就是一个简单的搜索树,求出来最大的 ...
- SGU Volume 1
SGU 解题报告(持续更新中...Ctrl+A可看题目类型): SGU101.Domino(多米诺骨牌)------------★★★type:图 SGU102.Coprimes(互质的数) SGU1 ...
- SGU 乱乱开
本解题报告 乱抄,乱写,随性随心,不喜多喷! SGU 142: 思路:一个string的字串不会超过2^20个,我们枚举出来就好了. 我出错点:数组RE #include<stdio.h> ...
- SGU 分类
http://acm.sgu.ru/problemset.php?contest=0&volume=1 101 Domino 欧拉路 102 Coprime 枚举/数学方法 103 Traff ...
- 快速切题 sgu134.Centroid 树形dp
134. Centroid time limit per test: 0.25 sec. memory limit per test: 4096 KB You are given an undirec ...
- SGU 乱搞日志
SGU 100 A+B :太神不会 SGU 101 Domino: 题目大意:有N张骨牌,两张骨牌有两面有0到6的数字,能相连当且仅当前后数字相同,问能否有将N张骨牌连接的方案?思路:裸的欧拉回路,注 ...
随机推荐
- 高效的TCP消息发送组件
目前的.net 架构下缺乏高效的TCP消息发送组件,而这种组件是构建高性能分布式应用所必需的.为此我结合多年的底层开发经验开发了一个.net 下的高效TCP消息发送组件.这个组件在异步发送时可以达到每 ...
- Atmospheric Scattering in Unity5
本次实践效果仅有Atmospheric Scattering和AA,并无其他post-processing,看到类似depth of field等的效果全部是Atmospheric Scatterin ...
- 【狼】unity 鼠标拖拽物体实现任意角度自旋转
主要涉及函数 Input.GetAxis(“Mouse x”) 可取得鼠标横向(x轴)移动增量 Input.GetAxis(“Mouse y”) 可取得鼠标竖向(y轴)移动增量 通过勾股定理获取拖拽长 ...
- MySQL生僻字(不常用字)的完整解决方案
查看 MySQL 数据库服务器和数据库字符集 show variables like '%char%'; 查看 MySQL 数据表(table) 的字符集 show table status from ...
- Pipe - POJ 1039(线段相交交点)
题目大意:有一个不反光并且不透光的管道,现在有一束光线从最左端进入,问能达到的最右端是多少,输出x坐标. 分析:刚开始做是直接枚举两个点然后和管道进行相交查询,不过这样做需要考虑的太多,细节不容易 ...
- Conversion between json and object
public static string ObjToJson<T>(T obj) { DataContractJsonSerializer serializer = new DataCon ...
- 【原创】javascript——事件思维导图
- HDU--5280(dp或枚举)
官方题解: 这个题有非常多O(n2)的算法.这里说一种:枚举每个区间,在枚举区间的同一时候维护区间内的最小值和区间和,将最小值与P的大小进行比較,贪心地取最大值就可以.注意若枚举到的区间是整个数组,则 ...
- 重复记录(duplicate records)相关运营数据
MySQL 中查找反复数据,删除反复数据 创建表和測试数据 /* 表结构 */ DROPTABLEIFEXISTS `t1`; CREATETABLEIFNOTEXISTS `t1`( `id` IN ...
- android 37 线程通信Looper
安卓程序的主线程也叫UI线程. 工作线程和主线程的差别:安卓主线程已经调用了Looper.prepare()方法了,已经有一个MessageQueue对象了,所以才可以在工作线程用Handler发消息 ...