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张骨牌连接的方案?思路:裸的欧拉回路,注 ...
随机推荐
- Linux Shell编程(21)——复杂命令
更高级的用户命令find-exec COMMAND \;在每一个find 匹配到的文件执行 COMMAND 命令. 命令序列以 ; 结束( ";" 是 转义符 以保证 shell ...
- Google Map API学习1
这一段时间公司一个新产品上线, 做超市代购的 这样,就需要计算每个门店也就是超市,距离小区之间的距离. 我们用的是Google Map 1.批量对地址进行编码,也就是将地址批量转化成对应的Goole ...
- 【原】ubuntu下Mysql的HA(corosync+pacemaker+drbd)
一.前提准备: 1.OS:ubuntu 12.04 2.cat /etc/hosts: 127.0.0.1 localhost 192.168.153.154 ha1 192.168.153.155 ...
- (一)Eclipse 快捷键
Ctrl+Alt+Down,即可以在下面快速复制一行 Ctrl+Alt+Up,即可以在上面快速复制一行. 1. ctrl+shift+r:打开资源 这可能是所有快捷键组合中最省时间的了.这组快捷键 ...
- hibernate之自定义持久化实现
- 系统调用和中断处理的异同(以Linux MIPS为例)
在Linux下写一个驱动时候遇到的读操作性能问题,让我想一窥系统调用的处理流程,以查出问题的root cause.很多书把它和中断处理放在一起讲,但是又没有哪本书说清楚了,看来只有代码才能说明一切.以 ...
- android 48 广播
系统开始重启会发送开机重启广播,电量低的时候会发送电量低的广播,广播注册有2种:系统说明文件xml注册和Java代码注册,前者是静态注册(全局注册)后者是动态注册(依赖于当时组建,组件销毁就收不到广播 ...
- systemTAP 学习
http://blog.csdn.net/moonvs2010/article/category/1570309
- 支付宝手机网站支付流程(Node实现)
前言 公司M站要接入支付宝,借机研究了一下支付宝的支付流程.毕竟,只有公司才能拿到支付接口权限. 主要参考文档: https://doc.open.alipay.com/doc2/detail?tre ...
- Service 如何知道caller
重写Binder的onTransact方法 1 you need to do that in Binder#onTransact method, this is a good place for ...