从叶节点开始修路肯定是最优的方式,这是一个很显然的结论,但要注意不要每次都去更新路径中所有结点,记录一下一个结点到根节点的路是否被修过,修过那么不必往上更新了。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <list>
#include <stack>
#include <cstring>
#include <queue>
#include <map>
#include <string>
using namespace std;
#define MAX 100005
#define ll long long
#define INF 0x3f3f3f3f
#define mod 1000000007
struct road {
int to, t;
};
struct deep {
int v, de;
friend bool operator<(const deep& a, const deep& b) {
return a.de < b.de;
}
};
int fa[MAX];
bool vis[MAX], rep[MAX];
vector<road> G[MAX];
priority_queue<deep> q;
void dfs1(int v,int c) {//预处理深度,结点的父节点
c++;
if (rep[v]) {
deep d;
d.de = c;
d.v = v;
q.push(d);
}
vis[v] = true;
for (int i = 0; i < G[v].size(); ++i) {
road& temp = G[v][i];
if (vis[temp.to]) continue;
fa[temp.to] = v;
if (temp.t == 2) rep[temp.to] = true;
dfs1(temp.to, c);
}
vis[v] = false;
}
void dfs2(int v) {
if (v == -1 || vis[v]) {
return;
}
vis[v] = true;
dfs2(fa[v]);
}
int main()
{
// freopen("a.txt", "r", stdin);
// freopen("b.txt", "w", stdout);
int n, x, y, t;
cin >> n;
for (int i = 1; i < n; ++i) {
scanf("%d%d%d", &x, &y, &t);
G[x].push_back(road{ y,t });
G[y].push_back(road{ x,t });
}
dfs1(1, 0);
fa[1] = -1;
stack<int> st;
while (!q.empty()) {
deep d = q.top();
q.pop();
if (vis[d.v]) continue;
st.push(d.v);
dfs2(d.v);
}
cout << st.size() << endl;
while (!st.empty()) {
cout << st.top() << endl;
st.pop();
}
return 0;
}