1143. [石门中学2009] 切割树
★ 输入文件:treecut.in
输出文件:treecut.out
简单对比
时间限制:1 s 内存限制:128 MB
treecut
题目描述:
有一个N个节点的无根树,各节点编号为1..N,现在要求你删除其中的一个点,使分割开的连通块中节点个数都不超过原来的一半多。
数据范围
1 <= N <= 10,000
输入文件 treecut.in
第一行:一个整数N。
后面有N-1行:每行两个整数 X 和 Y,表示一个边连接的两个节点号。
输出文件 treecut.out
输出所有可能选择的点。如果有多个节点,按编号从小到大输出,每个一行。 如果找不到这样的点,输出一行:"NONE".
样例
输入 |
10 1 2 2 3 3 4 4 5 6 7 7 8 8 9 9 10 3 8 |
样例说明: 删除3号或8号 节点,则分枝 最多有5个节点 |
输出 |
3 8 |
思路:dfs一边,然后枚举每个点作为切割点。
#include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 10001 using namespace std; vector<int>vec[MAXN]; int n,S,tot; int dad[MAXN],size[MAXN]; void dfs(int now){ size[now]=1; for(int i=0;i<vec[now].size();i++) if(dad[now]!=vec[now][i]){ dad[vec[now][i]]=now; dfs(vec[now][i]); size[now]+=size[vec[now][i]]; } } bool judge(int now){ if(size[1]-size[now]>S) return false; for(int i=0;i<vec[now].size();i++) if(dad[now]!=vec[now][i]){ int to=vec[now][i]; if(size[to]>S) return false; } return true; } int main(){ freopen("treecut.in","r",stdin); freopen("treecut.out","w",stdout); scanf("%d",&n); S=n/2; for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); vec[u].push_back(v); vec[v].push_back(u); } dfs(1); for(int i=1;i<=n;i++) if(judge(i)) cout<<i<<endl; }
时间: 2024-10-19 05:32:13