codeforces 369C

题意:给出一棵树, 边有两种 类型1, 代表路是好的, 类型2代表路是坏的, 我们要修复所有的路, 当我们修复结点x的时候, 那么它到结点1之间的所有路都会被修复,求最小的修路节点的集合

思路:对于节点x,它到父节点的边为类型2,那么如果节点x的所有子树都不存在类型为2的边,则将节点x加入子集,否则任意一个子树中的边得到维修,x到父节点的边也一定会被维修,这种情况x就不加入子集。

#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
const int qq = 1e5+10;
int top=0;
int num[qq];
int dp[qq];
int vis[qq];
struct Node{
	int to,type;
};
vector<Node>v[qq];
int dfs(int rt, int flag){
	int len = v[rt].size();
	int s=0;			//s是标记变量, s=0代表其子树中没有类型2的边,否则的话就代表有 
	vis[rt] = 1;		// 返回的变量可以消除标记、 
	for(int i=0; i<len; ++i){
		int son = v[rt][i].to;
		if(vis[son])	continue;
		if(v[rt][i].type==2)	s+=dfs(son, 1);
		else	s+=dfs(son, 0);
	}
	if(flag && !s){
		num[top++] = rt;
		return 1;
	}
	return s;
}
int main(){
	int n;scanf("%d",&n);
	Node tmp;
	for(int i=0; i<n-1; ++i){
		int a,b,c;scanf("%d%d%d",&a,&b,&c);
		tmp.to = b;
		tmp.type = c;
		v[a].push_back(tmp);
		tmp.to = a;
		v[b].push_back(tmp);
	}
	dfs(1, 0);
	printf("%d\n", top);
	for(int i=0; i<top; ++i)
		printf("%d ", num[i]);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值