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

代码参考:http://blog.csdn.net/u014258433/article/details/52454105?locationNum=9

代码:

#include<bits/stdc++.h>
#define maxn 400010
#define mod 1000000007
#define ll long long
#define pb push_back
#define fs first
#define se second
using namespace std;
const int INF=1e9+7;

int n;
vector<int> G[maxn];
int fson[maxn],sson[maxn],up[maxn],dw[maxn];
int siz[maxn],ans[maxn];

void dfs(int u,int fa)
{
    siz[u]=1;
    fson[u]=sson[u]=0;
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i];
        if(v==fa) continue;
        dfs(v,u);
        siz[u]+=siz[v];
        if(dw[v]>sson[u]) sson[u]=dw[v];
        if(fson[u]<sson[u]) swap(fson[u],sson[u]);
    }
    dw[u]=fson[u];
    if(siz[u]<=n/2) dw[u]=siz[u];
}

void dfs1(int u,int fa)
{
    if(fa!=-1)
    {
        up[u]=max(up[u],up[fa]);
        if(dw[u]!=fson[fa]) up[u]=max(up[u],fson[fa]);
        else  up[u]=max(up[u],sson[fa]);
        if(n-siz[u]<=n/2) up[u]=n-siz[u];
    }
    int tmp=0;
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i];
        if(v==fa) continue;
        dfs1(v,u);
        if(siz[v]>n/2) tmp=v;
    }
    if(n-siz[u]>n/2) tmp=-1;
    if(!tmp) ans[u]=1;
    else if(tmp>0)
    {
        if(siz[tmp]-dw[tmp]<=n/2) ans[u]=1;
    }
    else if(n-siz[u]-up[u]<=n/2) ans[u]=1;
}

int main()
{
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        G[x].pb(y);
        G[y].pb(x);
    }
    dfs(1,-1);
    dfs1(1,-1);
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    printf("\n");
    return 0;
}
时间: 2024-10-05 04:19:21

AIM Tech Round 3 (Div. 2) E. Centroids的相关文章

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 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>

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 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,

【AIM Tech Round 4 (Div. 2) D Prob】

·题目:D. Interactive LowerBound ·英文题,述大意:       有一个长度为n(n<=50000)的单链表,里面的元素是递增的.链表存储在一个数组里面,给出长度n.表头在数组的下标和一个值w.题目要求求出链表中大于等于w值的元素中的最小元素.注意,这道题是一道interactive.由于链表是未知的,最多可以进行1999个询问,询问形式:?i.表示询问数组下标为i,询问后,会得到一个答案组(val,Next),表示询问的元素是val,链表下一位所在的数组下标是Next

codeforces708b// Recover the String //AIM Tech Round 3 (Div. 1)

题意:有一个01组成的串,告知所有长度为2的子序列中,即00,01,10,11,的个数a,b,c,d.输出一种可能的串. 先求串中0,1的数目x,y. 首先,如果00的个数a不是0的话,设串中有x个0,C(X,2)=a,那么x*(x+1)=2a,解方程(其实只要看sqrt(x)*(sqrt(x)+1)等不等于2a),x没有整数解就IMPOSSIBLE.同理得出1的个数y.如果00个数是0看01个数. 第二,如果x*y!=b+c则IMPOSSIBLE,具体自己举个例子就明白. 最后,先将所有的0组

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 5 (rated, Div. 1 + Div. 2) A】 Find Square

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 找到左上角.往下一直走,往右一直走走到B边界就好. 中点的话.直接输出中位数 [代码] #include <bits/stdc++.h> #define LL long long #define rep1(i,a,b) for (int i = a;i <= b;i++) #define rep2(i,a,b) for (int i = a;i >= b;i--) #define all(x) x.begin(),