现在有一棵有 个节点的树,你可以删去树中的一些边使其成为森林,你的任务是删去最多的边使得每一棵森林中的树的大小为偶数,并输出删去的边数。
第一行为一个整数,即节点数 。
接下来 行每行包括两个整数 和 ,表示树中连接 和 的两条边。保证 和 在 至 的范围内,同时保证给出的图是一棵树。
一个整数,表示你可以删去的最多的边数。
首先,以 为根求出所有点的 和 。然后从叶子到根枚举,当一个点的 大小为偶数时,就把这个点的子树独自为一棵树。同时别忘了让它父亲的 减去它自己的 。
代码来源于洛谷用户HPXXZYY,请勿直接复制
codeforces账号也是HPXXZYY
const int N=1e5+100;
struct node{
int next,to;
}e[N<<1];int h[N],tot;
inline void add(int a,int b){
e[++tot]=(node){h[a],b};h[a]=tot;
e[++tot]=(node){h[b],a};h[b]=tot;
}
int n,size[N],fa[N],ans;
void dfs_init(int u,int pa){
size[u]=1;fa[u]=pa;int i;
for(i=h[u];i;i=e[i].next){
register int to=e[i].to;
if (to==pa) continue;
dfs_init(to,u);
size[u]+=size[to];
}
}
void calc_answer(int u){
for(int i=h[u];i;i=e[i].next)
if (e[i].to!=fa[u])
calc_answer(e[i].to);
if (size[u]%2==0){
ans++;size[fa[u]]-=size[u];
}
}
int main(){
freopen("t1.in","r",stdin);
n=read();ans=0;size[1]=0;
for(int i=1;i<n;i++)
add(read(),read());
if (n%2){
printf("-1");
return 0;
}
dfs_init(1,-1);
calc_answer(1);
cout<<ans-1;
return 0;
}
给你一个
个结点以
为根的树,给这
个结点任意染色,定义一个点为快乐结点
当且仅当这个结点的子树上所有点颜色
。求出对于
中的每一个
,求快乐结点
数大于等于
所需要的最少颜色数。
第一行一个数
,表示结点数量。
第二行 个数 ,表示第 个结点的父亲结点 。
一行,
个数,表示对于
中的每一个
,快乐节点
数大于等于
时所需的最少颜色数。
感谢洛谷的翻译,侵权必删!!!
考虑一棵子树,记其叶子节点为
,那么我们需要
种颜色让这棵子树的所有节点变成快乐节点
。所有我们只需求出所有的
,排序,输出即可。
代码来源于洛谷用户HPXXZYY,请勿直接复制
codeforces账号也是HPXXZYY
const int N=1e5+100;
vector<int> G[N];
int f[N],n,ans;
void dfs(int u){
f[u]=0;register int i;
for(i=0;i<G[u].size();i++){
register int to=G[u][i];
dfs(to);f[u]+=f[to];
}
if (f[u]==0) f[u]=1;
}
int main(){
n=read();ans=-1;
for(int i=2;i<=n;i++)
G[read()].push_back(i);
dfs(1);sort(f+1,f+n+1);
for(int i=1;i<=n;i++)
printf("%d ",f[i]);
return 0;
}