Codeforces708C Centroids

题目链接

题意:给定一棵n个结点的树,问:对于每个结点,能否通过删除一条边并添加一条边使得仍是树,并且删除该结点后得到的各个连通分量结点数 <= n/2?

题解:树形dp,两遍dfs,第一遍dfs求得以各个结点为根的子树的结点数,以及各个结点下面切掉某条边后最多可切出多少个结点;

第二遍dfs求得每个结点上面切掉某条边后最多可切出多少个结点。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N = 4e5+1;
 5 vector<int> ve[N];
 6 bool vis[N];
 7 int num[N], maxson[N], down[N], up[N];
 8 int n;
 9 void dfs(int x){
10     vis[x] = true;
11     num[x] = 1;
12     maxson[x] = 0;
13     down[x] = 0;
14     for(int i = 0; i < ve[x].size(); i++){
15         int y = ve[x][i];
16         if(vis[y]) continue ;
17         dfs(y);
18         num[x] += num[y];
19         maxson[x] = max(maxson[x], num[y]);
20         down[x] = max(down[x], num[y] <= n/2? num[y]: down[y]);
21     }
22 }
23 void debug(vector<int>& v){
24     puts("***");
25     cout << v.size() << endl;
26     for(int i = 0; i < v.size(); i++)
27         cout << v[i] << ‘ ‘;
28     puts("");
29     puts("****");
30 }
31 void dfs2(int f, int x){
32     vis[x] = true;
33     int tot = ve[x].size();
34     vector<int> tmp(tot), pre(tot), hou(tot);
35     for(int i = 0; i < tot; i++){
36         int y = ve[x][i];
37         if(vis[y]) tmp[i] = 0;
38         else
39             tmp[i] = num[y] <= n/2? num[y]:down[y];
40     }
41     for(int i = 0; i < tot; i++){
42         pre[i] = tmp[i];
43         if(i) pre[i] = max(pre[i], pre[i-1]);
44     }
45     for(int i = tot-1; i >= 0; i--){
46         hou[i] = tmp[i];
47         if(i != tot-1) hou[i] = max(hou[i], hou[i+1]);
48     }
49     for(int i = 0; i < tot; i++){
50         int y = ve[x][i];
51         if(vis[y]) continue ;
52         if(n-num[y] <= n/2)
53             up[y] = n-num[y];
54         else {
55             up[y] = up[x];
56             if(i+1 < tot)
57                 up[y] = max(up[y], hou[i+1]);
58             if(i-1 >= 0)
59                 up[y] = max(up[y], pre[i-1]);
60         }
61         dfs2(x, y);
62     }
63 }
64
65 int main(){
66     int u, v; scanf("%d", &n);
67     for(int i = 1; i < n; i++){
68         scanf("%d%d", &u, &v);
69         ve[u].push_back(v), ve[v].push_back(u);
70     }
71     dfs(1);
72     memset(vis, 0, sizeof(vis));
73     dfs2(0, 1);
74     bool tag;
75 //    for(int i = 1; i <= n; i++)
76 //        cout << maxson[i] << ‘ ‘ << num[i] << ‘ ‘ << down[i] << ‘ ‘ << up[i] << endl;
77     for(int i = 1; i <= n; i++){
78         if(maxson[i] <= n/2&&n-num[i] <= n/2)//不用切
79             tag = true;
80         else if(n-num[i] > n/2)//要切上面
81             tag = n-num[i]-up[i] <= n/2;
82         else//要切下面
83             tag = maxson[i]-down[i] <= n/2;
84         putchar(tag+‘0‘);
85         putchar(i == n? ‘\n‘:‘ ‘);
86     }
87     return 0;
88 }
时间: 2024-10-31 02:38:49

Codeforces708C Centroids的相关文章

[CF708C]Centroids

Centroids 题目大意 一棵树,对于每个点,我们删掉任意一条边,再连上任意一条边,求这样操作后可以使这个点为重心的点数 范围\(n\)级别 Solution 嗯,首先对于一个点\(u\),若全部子树(包括自己头上的那一堆)都不到总点数\(n\)的一半的肯定符合条件 然后若\(u\)的子树\(\{ v \}\)中有一个点数\(> {n \over 2}\)的\(v1\),我们要在这样的子树中找到最大的一棵点数\(<= {n \over 2}\)的子树 \(v2\). 把它断开来,然后把\(

AIM Tech Round 3 (Div. 2) E. Centroids

题解: 树形dp 非常好的一道题目 题意: 对于每个点.更改一条边,能否使得这个点成为树的重心 题解: 所谓重心:指去掉这个点后,最大的连通分量的点数<=n/2 对于每个点,分为向下分析,向上分析 向下分析:找寻点u的子节点的最大节点v.然后找寻节点v的子节点的小于等于n/2的最大子节点,连接到u上 向上分析:找寻点u的父节点的最大节点v.如果v==u那么.找寻次大节点w.然后找寻该点的子节点的小于等于n/2的最大子节点,连接到u上 向下分析和向上分析只需要判断一个,因为大于n/2的点只有一个

Weka开发[9]—KMeans源码介绍

以前介绍的都是分类的内容,这一次介绍聚类,以最简单的SimpleKMeans源码为例. 分类中训练一个分类器是用buildClassifier(),在聚类中学习一个Clusterer是用buildCluster().分类中分类一个样本是用classifyInstance,而在聚类中是用clusterInstance.那我怎么知道这些的呢?(或者说:你怎么知道我是不是在骗你呢?)以ID3为例,你可以看出它继承自Classifier类,进入Classifier类,它有三个比较重要的函数,buildC

《机器学习实战》之K-均值聚类算法的python实现

<机器学习实战>之K-均值聚类算法的python实现 最近的项目是关于"基于数据挖掘的电路故障分析",项目基本上都是师兄们在做,我只是在研究关于项目中用到的如下几种算法:二分均值聚类.最近邻分类.基于规则的分类器以及支持向量机.基于项目的保密性(其实也没有什么保密的,但是怕以后老板看到我写的这篇博文,所以,你懂的),这里就不介绍"基于数据挖掘的电路故障分析"的思路了. 废话不多说了,开始正题哈. 基本K-均值聚类算法 基本K均值算法的基本思路为:首先选择

Motion-Based Multiple Object Tracking

kalman filter tracking... %% Motion-Based Multiple Object Tracking % This example shows how to perform automatic detection and motion-based % tracking of moving objects in a video from a stationary camera. % % Copyright 2014 The MathWorks, Inc. %% %

GMM+Kalman Filter+Blob 目标跟踪

转 http://www.cnblogs.com/YangQiaoblog/p/5462453.html ==========图片版============================================================================== ===================================================================================== 最近学习了一下多目标跟踪,看了看Mat

Python—kmeans算法学习笔记

一.   什么是聚类 聚类简单的说就是要把一个文档集合根据文档的相似性把文档分成若干类,但是究竟分成多少类,这个要取决于文档集合里文档自身的性质.下面这个图就是一个简单的例子,我们可以把不同的文档聚合为3类.另外聚类是典型的无指导学习,所谓无指导学习是指不需要有人干预,无须人为文档进行标注. 二.聚类算法:from sklearn.cluster import KMeans def __init__(self, n_clusters=8, init='k-means++', n_init=10,

《机器学习》周志华 习题答案9.4

原题采用Kmeans方法对西瓜数据集进行聚类.我花了一些时间居然没找到西瓜数据集4.0在哪里,于是直接采用sklearn给的例子来分析一遍,更能说明Kmeans的效果. #!/usr/bin/python # -*- coding:utf-8 -*- import numpy as np import matplotlib.pyplot as plt from sklearn.ensemble import BaggingClassifier from sklearn.tree import D

机器学习系列(9)_机器学习算法一览(附Python和R代码)

本文资源翻译@酒酒Angie:伊利诺伊大学香槟分校统计学同学,大四在读,即将开始计算机的研究生学习.希望认识更多喜欢大数据和机器学习的朋友,互相交流学习. 内容校正调整:寒小阳 && 龙心尘 时间:2016年4月 出处:http://blog.csdn.net/han_xiaoyang/article/details/51191386 http://blog.csdn.net/longxinchen_ml/article/details/51192086 声明:版权所有,转载请联系作者并注