2021-11-05


import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;

public class Solution {

    public static void main(String[] args) throws IOException {
        for (int i = 0; i < MaxN; i++) {
            adj.add(new ArrayList<>());
        }
        in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        int T = nextInt();
        for (int tc = 1; tc <= T; tc++) {
            readCase();
            work();
            System.out.println("#" + tc + " " + ans1 + " " + ans2);
        }
    }

    static void work() throws IOException {
        Arrays.fill(outD, 0, N + 1, Integer.MAX_VALUE);
        for (int i = 1; i <= N; i++) {
            if (inD[i] == 0) {
                dfs(i, 0, 0);
            }
        }
        ans1 = 0;
        ans2 = 0;
        for (int i = 1; i <= Q; i++) {
            int a = nextInt();
            int b = nextInt();
            int ca = getLca(a, b);
            if (ca == 0) {
                ans2++;
            } else {
                ans1 += (sum[a] - sum[ca]) + (sum[b] - sum[ca]);
            }
        }
        Arrays.fill(inD, 0, N + 1, 0);
        Arrays.fill(sum, 0, N + 1, 0);
        for (int i = 0; i < 20; i++) {
            Arrays.fill(f[i], 0, N + 1, 0);
        }
    }

    static int getLca(int a, int b) {
        if (isContains(b, a)) return a;
        for (int i = 19; i >= 0; i--) {
            if (isContains(b, f[i][a])) continue;
            a = f[i][a];
        }
        return f[0][a];
    }

    static boolean isContains(int a, int b) {
        return inD[b] <= inD[a] && outD[b] >= outD[a];
    }

    static void dfs(int cur, int fa, int len) {
        f[0][cur] = fa;
        for (int i = 1; i < 20; i++) {
            f[i][cur] = f[i - 1][f[i - 1][cur]];
            if (f[i][cur] == 0) break;
        }
        sum[cur] = sum[fa] + len;
        inD[cur] = timer_seq++;
        for (int[] nx : adj.get(cur)) {
            if (fa == nx[0]) continue;
            dfs(nx[0], cur, nx[1]);
        }
        outD[cur] = timer_seq++;
    }

    static void readCase() throws IOException {
        N = nextInt();
        M = nextInt();
        Q = nextInt();
        for (int i = 1; i <= N; i++) {
            adj.get(i).clear();
        }
        for (int i = 1; i <= M; i++) {
            int a = nextInt();
            int b = nextInt();
            int c = nextInt();
            adj.get(a).add(new int[]{b, c});
            adj.get(b).add(new int[]{a, c});
        }
    }

    static int nextInt() throws IOException {
        in.nextToken();
        return (int) in.nval;
    }

    static StreamTokenizer in;
    static final int MaxN = 100003;
    static final int[] inD = new int[MaxN];
    static final int[] outD = new int[MaxN];
    static final int[][] f = new int[20][MaxN];
    static final long[] sum = new long[MaxN];
    static final ArrayList<ArrayList<int[]>> adj = new ArrayList<>();
    static int N, M, Q, timer_seq;
    static long ans1, ans2;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值