A. Valera and Plates 模拟
B. Valera and Contest 构造
C. Valera and Elections
http://codeforces.com/contest/369/problem/C
我的思路是首先dfs把树建起来,然后对每条需要修的边,从离树根远的那个开始向上标记,直到根节点,这样就构成了一颗新的树,新的树中的叶子节点就是所求节点,标记时候把叶子和中间节点区分开就行了。由于n比较大,要防止退化成一条链的情况,遇到标记过的,就不再向上重复标记了。
没用过邻接表,加上开始思路不是很明确,直接卡了一小时。
# include <stdio.h> # include <vector> using namespace std; # define N 100005 int n; vector <int> vec[N]; int sz[N]; int u[N], v[N], w[N]; int fa[N]; bool vis[N]; int color[N]; void dfs(int cur) { for (int i = 0; i < vec[cur].size(); ++i) { int v = vec[cur][i]; if (!vis[v]) { vis[v] = true; fa[v] = cur; dfs(v); } } } int main() { scanf("%d", &n); for (int i = 0; i < n-1; ++i) { scanf("%d%d%d", &u[i], &v[i], &w[i]); vec[u[i]].push_back(v[i]); vec[v[i]].push_back(u[i]); } vis[1] = true; dfs(1); for (int i = 0; i < n-1; ++i) if (w[i] == 2) { int cur; if ( fa[ u[i] ] == v[i] ) { cur = u[i]; }else { cur = v[i]; } if (color[cur] == 0) { color[cur] = 1; cur = fa[cur]; while (color[cur] <= 1) { color[cur] = 2; if (cur == 1) break; cur = fa[cur]; } } else ++color[cur]; } int cnt = 0; for (int i = 1; i <= n; ++i) if (color[i] == 1) { ++cnt; } printf("%d ", cnt); for (int i = 1; i <= n; ++i) if (color[i] == 1) { printf("%d ", i); } printf(" "); return 0; }