http://codeforces.com/contest/369/problem/C
做题时一直纠结于该怎么建立一颗多叉树,怎么存储比较合理而又方便。。。后来看到有人用vector存树,有点儿茅塞顿开的感觉。。。
1)用vector数组保存每个节点的子节点;
2)深搜,找到每个节点的父节点,从而建立一棵树;
3)遍历边,若某条边有问题则将该边的子节点col值赋1,沿该节点向上直至根节点的每一个节点的col值赋2。。。。。。
4)最后col值为1的节点即为problem road所在路径的叶节点,即为所求。
具体代码与注释如下:
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
#include <string>
#include <math.h>
#define N 100010
using namespace std;
int n;
struct road{
int x,y,t;
}r[N];
vector <int> v[N];//存储每个节点的各个子节点
int par[N]; //记录各节点的父亲节点
int vis[N],col[N];
//深搜,建树,找到各个节点的父节点
void dfs(int cur)
{
for(int i=0;i<v[cur].size();i++){
int u=v[cur][i];
if(!vis[u]) {
vis[u]=1;
par[u]=cur;
dfs(u);
}
}
}
int main()
{
int x,y,t;
int i,j,min;
while(scanf("%d",&n)!=EOF){
memset(vis,0,sizeof(vis));
memset(col,0,sizeof(col));
memset(par,0,sizeof(par));
for(i=0;i<=n;i++) v[i].clear();
for(i=0;i<n-1;i++){
scanf("%d %d %d",&r[i].x,&r[i].y,&r[i].t);
v[r[i].x].push_back(r[i].y);
v[r[i].y].push_back(r[i].x);
}
vis[1]=1;
dfs(1);
for(i=0;i<n-1;i++){
if(r[i].t==2){ //若该边有问题
int cur;
if(par[r[i].x]==r[i].y){ //y为父节点
cur=r[i].x;
}
else{ //x为父节点
cur=r[i].y;
}
if(col[cur]==0){
col[cur]=1; //从该节点向上追溯,col值加一
cur=par[cur];
while(col[cur]<=1){
col[cur]=2;
if(cur==1) break; //已达根部
cur=par[cur];
}
}
else col[cur]++;
}
}
min=0;
for(i=1;i<=n;i++)
if(col[i]==1) //该节点为有问题路所在分支的叶节点
min++;
printf("%d\n",min);
int flag=1;
for(i=1;i<=n;i++)
if(col[i]==1){
if(flag){
printf("%d",i);
flag=0;
}
else{
printf(" %d",i);
}
}
printf("\n");
}
return 0;
}