题目:http://codeforces.com/problemset/problem/369/C
题意:n个点,n-1条边的树,以1为根,边的权值有1:好路,2:坏路。从n个点选取最少的节点使到1节点的路径经过所有的坏路。
思路:dfs。对叶子节点:若连接其父节点的边权为2,则此叶子节点是必选的。
对非叶子节点:若连接其父节点的边权为2且子树中没有节点被选中,则也是必选的。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
struct Edge{
int to, nxt, w;
}edge[maxn<<1];
vector<int>vec;
int n, num_edge, head[maxn], vis[maxn];
void addedge(int u, int v, int w){
edge[++num_edge].to = v;
edge[num_edge].w = w;
edge[num_edge].nxt = head[u];
head[u] = num_edge;
}
int dfs(int rt, int w){
bool flag = false; int res = 0;
for(int i=head[rt]; ~i; i=edge[i].nxt){
int to = edge[i].to;
if(!vis[to]){
vis[to] = 1;
flag = true;
res += dfs(to, edge[i].w); //边的权值下传给儿子
}
}
if(!flag) { //叶子节点
if(w == 2) {vec.push_back(rt); return 1;}
return 0;
}
if(res == 0 && w == 2) {vec.push_back(rt); return 1;}
return res;
}
int main()
{
int u, v, w;
memset(head, -1, sizeof head);
cin >> n;
for(int i=1; i<n; i++){
cin >> u >> v >> w;
addedge(u, v, w);
addedge(v, u, w);
}
vis[1] = 1; dfs(1, 1);
cout << vec.size() << endl;
if(vec.size()) for(auto it : vec) cout << it << " "; cout << endl;
}