题目
说明
N台计算机由N-1条网线连接,形成了一个树形网络。这些计算机经常会被黑客攻击,如果这个树形网络中的某一台计算机遭到攻击而导致系统瘫痪,那么与这台计算机连接的所有网线就无法进行数据传输,整个网络就会被分成若干个小的树形网络,每个小网络由一台或多台计算机组成。如果一台计算机被攻击后,形成的每个小网络中包含的计算机数都不超过N/2,那么这台计算机就会成为重点攻击对象,称作“危险计算机”。给定一个树形网络,请你找出网络中所有的“危险计算机”。
输入格式
第一行是一个整数N(1≤N ≤20000),表示计算机的台数,计算机被编号为1..N。下面N-1行,每行包括两个整数X, Y,表示X和Y这两台计算机之间由一条网线连接。
输出格式
包括若干行,每行为一台危险计算机的编号,按升序排列。如果没有危险计算机,就输出一行,只包含一个字符串“NONE”(不包括引号)
样例
输入数据 1
10
1 2
2 3
3 4
4 5
6 7
7 8
8 9
9 10
3 8
输出数据 1
3
8
思路
先读入数据并双向建边,然后在dfs过程中求出以u的直属子节点为根的子树中节点最多数量和以u为根的子树中有多少个节点
,最后枚举所有点,判断以i的直属子节点为根的子树中节点最多数量是否<=n/2,是则输出i,标记fl为0(初始为1),最后判断如果fl == 1,输出"NONE"
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,h[1000001],vtx[1000001],nxt[1000001],ans[1000001],t,eg,a[1000001],v[1000001];
bool fl = 1;
void adeg(int u,int v)
{
eg++;
nxt[eg] = h[u];
h[u] = eg;
vtx[eg] = v;
}
void dfs(int u,int fa)
{
//ans[u]:以u的直属子节点为根的子树中节点最多数量
//v[u]:以u为根的子树中有多少个节点
v[u] = 1;
ans[u] = 0;
for(int i = h[u];i;i = nxt[i])
{
int t = vtx[i];
if(t == fa) continue;
dfs(t,u);
v[u] += v[t];
ans[u] = max(ans[u],v[t]);
}
ans[u] = max(ans[u],n - v[u]);
}
signed main()
{
cin>>n;
for(int i = 1; i < n; i++)
{
int a,b;
cin>>a>>b;
adeg(a,b);
adeg(b,a);
}
dfs(1,0);
for(int i = 1;i <= n;i++)
if(ans[i] <= n / 2)
{
cout<<i<<endl;
fl = 0;
}
if(fl) cout<<"NONE";
return 0;
}