Problem:
Weighted Union Find Trees

There is a sequence $A = a_0, a_1, ..., a_{n-1}$. You are given the following information and questions.

relate$(x, y, z)$: $a_y$ is greater than $a_x$ by $z$

diff$(x, y)$: report the difference between $a_x$ and $a_y$ $(a_y - a_x)$

Input

$n \; q$
$query_1$
$query_2$
:
$query_q$

In the first line, $n$ and $q$ are given. Then, $q$ information/questions are given in the following format.

0 $x \; y\; z$

or

1 $x \; y$

where '0' of the first digit denotes the relate information and '1' denotes the diff question.

Output

For each diff question, print the difference between $a_x$ and $a_y$ $(a_y - a_x)$.

Constraints

$2 \leq n \leq 100,000$

$1 \leq q \leq 200,000$

$0 \leq x, y < n$

$x \ne y$

$0 \leq z \leq 10000$

There are no inconsistency in the given information

Sample Input

5 6
0 0 2 5
0 1 2 3
1 0 1
1 1 3
0 1 4 8
1 0 4

Sample Output

2
?
10

Solution in JAVA (judge verdict: Wrong Answer)

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

// disjoin set
public class Main {
    static class UnionFindTree {

        private int parent[];
        private int rank[];
        private int weight[];

        public UnionFindTree(int Num_element) {
            parent = new int[Num_element];
            rank = new int[Num_element];
            weight = new int[Num_element];
            for (int i = 0; i < Num_element; i++)
                makeSet(i);
        }

        public void makeSet(int x) {
            parent[x] = x;
            rank[x] = 0;
            weight[x] = 0;
        }

        public void union(int x, int y, int cost) {
            link(findSet(x), findSet(y), cost - weight[x] + weight[y]);
        }

        public int findSet(int x) {
            if (parent[x] != x) {
                parent[x] = findSet(parent[x]);
                int tmp = parent[x];
                weight[x] += weight[parent[x]];
                parent[x] = tmp;
            }
            return parent[x];
        }
        public boolean same(int x,int y){
            return findSet(x) == findSet(y);
        }

        public void link(int x, int y, int cost) {
            if (rank[x] > rank[y]) {
                parent[y] = x;
                weight[y] -= cost;
            } else {
                parent[x] = y;
                weight[x] += cost;
                if (rank[x] == rank[y]) {
                    rank[y]++;
                }
            }
        }

        public int sum(int x) {
            int sum = 0;
            int now = x;
            while ((now != parent[now])) {
                sum += weight[now];
                now = parent[now];
            }
            return sum;
        }

    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // Disjoin set element number
        int Num_element;

        //Query times
        int Num_query;


        Num_element = sc.nextInt();
        Num_query = sc.nextInt();
        UnionFindTree Disjoin_set = new UnionFindTree(Num_element);
        for (int i = 0; i < Num_query; i++) {
            // '0' denotes unite and '1' denotes same operation.
            int com = sc.nextInt();
            int x = sc.nextInt();
            int y = sc.nextInt();
            if (com == 0) {
                int z = sc.nextInt();
                Disjoin_set.union(x, y, z);
            } else {
                if(!Disjoin_set.same(x,y)){
                    System.out.println("?");
                }else
                    System.out.println(Disjoin_set.sum(x) - Disjoin_set.sum(y));
            }
        }

    }
}