#1515 : 分数调查
带权并查集。
1 /* 2 如果把每个人抽象成一个点,之间的关系抽象成边。 3 那么如果询问的两个人之间存在关系,说明,他们在图上上是联通的。 4 所以并查集维护一下连通性。 5 对于分数之间的关系,用到带权并查集。 6 每个点里存一个val表示当前点的分数-根节点的分数。 7 查询: 8 xy不连通,输出-1, 9 否则val[x]=fen[x]-fen[u],val[y]=fen[y]-fen[u],输出fen[x]-fen[y]=val[x]-val[y] 10 合并: 11 x的根节点为u,y的根节点为v,fa[u]=v; 12 更新后的val[u]=fen[u]-fen[v], 13 val[x]=fen[x]-fen[u] -> fen[u]=fen[x]-val[x] 14 val[y]=fen[y]-fen[v] -> fen[v]=fen[y]-val[y] 15 fen[u]-fen[v] = fen[x] - fen[y] + val[y] - val[x] = S + val[y] - val[x] 16 */ 17 #include<bits/stdc++.h> 18 using namespace std; 19 typedef long long LL; 20 21 inline int read() { 22 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 23 for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 24 } 25 26 const int N = 100010; 27 int fa[N],val[N]; 28 29 int find(int x) { 30 if (x == fa[x]) return x; 31 int tmp = find(fa[x]); 32 val[x] += val[fa[x]]; 33 fa[x] = tmp; 34 return fa[x]; 35 } 36 int main() { 37 int n = read(), m = read(), k = read(); 38 for (int i=0; i<=n; ++i) 39 fa[i] = i, val[i] = 0; 40 for (int i=1; i<=m; ++i) { 41 int x = read(),y = read(),S = read(); 42 int u = find(x),v = find(y); 43 if (u != v) { 44 fa[u] = v; 45 val[u] = val[y] - val[x] + S; 46 } 47 } 48 while (k--) { 49 int x = read(),y = read(); 50 if (find(x) != find(y)) puts("-1"); 51 else { 52 printf("%d\n",val[x]-val[y]); 53 } 54 } 55 return 0; 56 }