use std::io::*;
use std::str::FromStr;
use utils::*;

pub fn main() {
    let i = stdin();
    let mut o = Vec::new();
    run(i.lock(), &mut o);
    stdout().write_all(&o).unwrap();
}

fn run<R: BufRead, W: Write>(i: R, o: &mut W) {
    let mut i = CpReader::new(i);
    let n = i.read::<usize>();

    let mut edges = VecVec::new(n, (n - 1) * 2);
    for _ in 0..n - 1 {
        let (u, v, w) = i.read3::<usize, usize, usize>();
        let (u, v, w) = (u - 1, v - 1, (w % 2) as u8);
        edges.push(u, (v, w));
        edges.push(v, (u, w));
    }
    let mut ds = vec![0; n];
    let mut q = vec![(0, 0, 0)];
    while let Some((i0, i1, d)) = q.pop() {
        ds[i1] = d;
        for &(i2, w) in edges.get(i1) {
            if i2 != i0 {
                q.push((i1, i2, d ^ w));
            }
        }
    }
    for d in ds {
        writeln!(o, "{}", d).unwrap();
    }
}

mod utils {
    use super::*;

    pub struct CpReader<R: BufRead> {
        r: R,
        s: String,
    }

    macro_rules! fn_read {
        { $f:ident($($t:ident),*) } => {
            #[allow(dead_code)]
            pub fn $f<$($t: FromStr),*>(&mut self) -> ($($t),*) {
                let i = &mut self.read_line().split(' ');
                ($(read_next::<$t,_>(i)),*)
            }
        };
    }

    impl<R: BufRead> CpReader<R> {
        pub fn new(r: R) -> Self {
            CpReader {
                r: r,
                s: String::new(),
            }
        }
        pub fn read_line(&mut self) -> &str {
            self.s.clear();
            self.r.read_line(&mut self.s).unwrap();
            self.s.trim()
        }

        pub fn read<T: FromStr>(&mut self) -> T {
            self.read_line().parse().ok().unwrap()
        }
        fn_read! { read2(T1, T2) }
        fn_read! { read3(T1, T2, T3) }
        fn_read! { read4(T1, T2, T3, T4) }
        fn_read! { read5(T1, T2, T3, T4, T5) }
    }
    fn read_next<'a, T: FromStr, I: Iterator<Item = &'a str>>(i: &mut I) -> T {
        i.next().unwrap().parse().ok().unwrap()
    }

    pub struct VecVec<T> {
        hs: Vec<Option<usize>>,
        vs: Vec<(T, Option<usize>)>,
    }
    #[allow(dead_code)]
    impl<T> VecVec<T> {
        #[inline]
        pub fn new(len: usize, capacity: usize) -> Self {
            VecVec {
                hs: vec![None; len],
                vs: Vec::with_capacity(capacity),
            }
        }

        #[inline]
        pub fn push(&mut self, idx: usize, value: T) {
            self.vs.push((value, self.hs[idx]));
            self.hs[idx] = Some(self.vs.len() - 1);
        }

        #[inline]
        pub fn len(&self) -> usize {
            self.hs.len()
        }

        #[inline]
        pub fn get(&self, idx: usize) -> VecVecIter<T> {
            VecVecIter {
                s: self,
                i: self.hs[idx],
            }
        }
    }
    pub struct VecVecIter<'a, T: 'a> {
        s: &'a VecVec<T>,
        i: Option<usize>,
    }
    impl<'a, T: 'a> Iterator for VecVecIter<'a, T> {
        type Item = &'a T;

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            if let Some(i) = self.i {
                self.i = self.s.vs[i].1;
                Some(&self.s.vs[i].0)
            } else {
                None
            }
        }
    }


}


Measured memory_bytes: 14588