HZOI20190821模拟28题解

题面:https://www.cnblogs.com/Juve/articles/11390839.html

所有官方正解在我的文件里

A. 虎

算法1:我们发现非关键边与黑色边去掉以后,答案就是将所有度数为奇数的点作为路径的端点,所以记去掉非关键边与黑色边以后度数为奇数的点的个数为s,而一条路径有2个端点,所以答案就是$\frac{s}{2}$。

注意映射

#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN 1000005
using namespace std;
int n,ans=0,du[MAXN],id[MAXN],tot=0;
signed main(){
	scanf("%d",&n);
	for(int i=2,x,y,z;i<=n;i++){
		scanf("%d%d%d",&x,&y,&z);
		if(z==0){
			if(id[i]) id[x]=id[i];
			else if(id[x]) id[i]=id[x];
			else id[x]=id[i]=++tot;
		}
		if(y==0){
			if(!id[i]) id[i]=++tot;
			if(!id[x]) id[x]=++tot;
			du[id[i]]++,du[id[x]]++;
		}
	}
	for(int i=2;i<=tot;i++){
		if(du[i]&1) ans++;
	}
	printf("%d\n",(ans+1)/2);
	return 0;
}

算法2:不妨设0号点为根,那么将i到j的路径取反等价于将0到i和0到j的路径取反,因此只要求出最少需要将多少条到根的路径取反,然后除以二上取整就是答案。用f[i]表示i的子树中所有边(包括 i 连向父亲的边)满足条件时的最少取反路径数,只要先对i的所有儿子的f值求和,然后判断i连向父亲的边是否满足条件,如果不满足再+1即可。

猜你喜欢

转载自www.cnblogs.com/Juve/p/11390895.html
今日推荐