AIM Tech R3 div2 E Centroid

思路很明显了,假设是点x,则看它的子树中是否有大于n/2的,如果有,则在该子树中剪去它可以剪的且小于n/2的,接到点x上。

则统计出在以x点为根的子树中,它的各子树可以剪去的且小于n/2的最大子子树。对于除去以x为根的子树的其他部分,记为up,则同样地统计它的可以剪除的符合条件的子树,最后对每个点判断一下就可以了。

代码如下::(额,想的时候对up的这个不知道怎么写~谢指导)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
//#include <bitset>
using namespace std;

const int MAXN = 400010;

vector<int> t[MAXN];
int par[MAXN], sz[MAXN], up[MAXN], dw[MAXN], n;

void dfs_sz(int u, int parent){
	par[u] = parent;
	sz[u] = 1;
	int size = t[u].size();
	for(int i = 0; i< size; i++){
		int v = t[u][i];
		if(v == parent) continue;
		dfs_sz(v, u);
		sz[u] += sz[v];
	}
}

void dfs_down(int u, int parent){
	dw[u] = (sz[u] <= n/2 ? sz[u] : 0);
	int size = t[u].size();
	for(int i = 0; i < size; i++){
		int v = t[u][i];
		if(v == parent) continue;
		dfs_down(v, u);
		dw[u] = max(dw[u], dw[v]);
	}
}

void dfs_up(int u, int parent, int val){
	up[u] = max((n - sz[u] <= n /2? n - sz[u]: 0), val);
	int size = t[u].size();

	int mx0 = 0, mx1 = 0;

	for(int i = 0; i < size; i++){
		int v = t[u][i];
		if(v == parent) continue;
		if(dw[v] >= mx0){
			mx1 = mx0;
			mx0 = dw[v];
		}
		else if(dw[v] >= mx1){
			mx1 = dw[v];
		}
	}

	for(int i = 0; i < size ; i++){
		int v = t[u][i];
		if(v == parent) continue;
		dfs_up(v, u, max(up[u], (mx0 == dw[v]? mx1 : mx0 )));

	}

}

int main(){

	int u, v;

	scanf("%d", &n);
	for(int i = 1; i< n; i++){
		scanf("%d%d", &u, &v);
		t[u].push_back(v);
		t[v].push_back(u);
	}

	dfs_sz(1, -1);
	dfs_down(1, -1);
	dfs_up(1, -1, 0);

	for(int i = 1; i <= n; i++){
		int ans = 1;
		int size = t[i].size();
		for(int k = 0; k < size; k++){
			int u = t[i][k];
			if(u == par[i]){
				if(n - sz[i] - up[i] > n/2)
					ans = 0;
			}
			else {
				if(sz[u] - dw[u] > n/ 2)
					ans = 0;
			}

		}
		printf("%d", ans);
		if(i == n) printf("\n");
		else printf(" ");

	}

	return 0;
}

  

时间: 2024-09-30 14:24:21

AIM Tech R3 div2 E Centroid的相关文章

Codeforces Aim Tech Round4 (Div2) D

题目链接: 题意: 给你一个严格升序的单链表,但是是用数组来存放的.对于每一个位置来说,你可以知道这个位置的值和下一个的位置.你每一个可以询问一个位置,机器会告诉你这个位置的值,和下一个位置的指针.要你确认大于等于x的值.(询问次数不能超过2000). 题解: 由于给你的可能有5e4个数,除了随机算法,没有一种可以在2000步以内找到小于等于x. 对与随机算法:我们先随机找500个点,找到小于x的点0值中最大的一个.然后暴力询问.小于2000的直接暴力找了. 证明: 我们假设x的位置在Y, 那么

AIM Tech Round 3 (Div. 2)

5/5 这一场是比较水的一场(当然我是指div2),所以前面三题就略过吧... 题D D. Recover the String 题意:让你构造一个01串,给你00,01,10,11的子序列个数,问你有没有满足的串. 题解:这题实际上并不难, 只是分类讨论有点麻烦. 首先是00和11一定是满足n * (n - 1)  / 2,先判定一下 然后得到0的个数x,1的个数y 然后我们注意到,现一开始所有的0放在一起,然后插入一个位置k,那么我们发现01多了k,10多了x – k:假设这y个1 的位置是

AIM Tech Round 3 (Div. 2) B

Description Vasya takes part in the orienteering competition. There are n checkpoints located along the line at coordinates x1, x2, ..., xn. Vasya starts at the point with coordinate a. His goal is to visit at least n - 1 checkpoint in order to finis

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的点只有一个

AIM Tech Round 4 (Div. 2)

A题 分析:暴力 1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "string" 5 using namespace std; 6 const int maxn=100+10; 7 int vis[maxn],n; 8 string s; 9 int main() 10 { 11 cin>>s; 12 cin>

Codeforces AIM Tech Round3

打得最烂一场Codeforces,多次都错题,无限WA... A题: 题意:给定n个橘子的大小,大小超过b的丢掉,不足d的补充进来,同时超过d的部分去掉,问要去掉几次 分析:直接模拟即可 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <vector> 6 #include <algorithm>

AIM Tech Round (Div. 2)

A. Save Luke 题意:给一个人的长度d,然后给一个区间长度0~L,给你两个子弹的速度v1,v2,两颗子弹从0和L向中间射去(其实不是子弹,是一种电影里面那种绞牙机之类的东西就是一个人被困在里面了,两边有着那种尖刺的墙向中间靠拢的那种)问Luke能存活的最长时间 思路:看代码吧,简单易懂 1 #include<cstdio> 2 #include<cmath> 3 int main() 4 { 5 int d,l,v1,v2; 6 while(scanf("%d%

AIM Tech Round 4 (Div. 2) A B C

A. Diversity 题意:给出一个字符串,和n,问最多改变多少个字符,使其不同字符最少为n 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10; 5 6 map<char ,int >ma; 7 int main(){ 8 string s; 9 cin>>s; 10 int n; 11 cin>>n; 12 int

AIM Tech Round 4 (Div. 2)(A,暴力,B,组合数,C,STL+排序)

A. Diversity time limit per test:1 second memory limit per test:256 megabytes input:standard input output:standard output Calculate the minimum number of characters you need to change in the string s, so that it contains at least k different letters,