题意:给出整数N,M,Q。代表有N个同学,编号为1-N,M个信息,Q个询问。接下来有M行,每一行有三个整数x,y,s,表示x的分数比y大s。然后有Q行,每行给出x,y,询问x比y高几分,如果不可知,输出-1。
题解:定义fa[i]为i的父亲,v[i]是i比父亲多几分。带权并查集,进行更新即可。
#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
int fa[100005],v[100005];
//the ordinary Union Find algorithm
/*
int findfa(int rt)
{
if(fa[rt]!=rt) fa[rt]=findfa(fa[rt]);
return fa[rt];
}
void u(int x,int y)
{
int fa1,fa2;
fa1=findfa(x);
fa2=findfa(y);
fa[fa1]=fa2;
}
*/
//the weighted Union Find algorithm
int findfa(int rt)
{
if(fa[rt]!=rt){
int temp =fa[rt];
fa[rt]=findfa(fa[rt]);
v[rt]=v[rt]+v[temp];
}
return fa[rt];
}
void u(int x,int y,int s)
{
int fa1,fa2;
fa1=findfa(x);fa2=findfa(y);
if(fa1!=fa2){
fa[fa1]=y;
//because v[x]+v[fa[x]]=s
//if modify the last scope to fa[fa1]=fa2, how would the v[fa1] be?
v[fa1]=s-v[x];
}
}
int main(void)
{
int n,m,q,x,y,s;
scanf("%d%d%d",&n,&m,&q);
//initial everyone's father to himself, v[i]=0
for(int i=1;i<=n;i++){
fa[i]=i;
//v[i]=0;
}
int fa1,fa2;
for(int i=0;i<m;i++){
scanf("%d%d%d",&x,&y,&s);
fa1=findfa(x);fa2=findfa(y);
u(x,y,s);
}
for(int i=0;i<q;i++){
scanf("%d%d",&x,&y);
fa1=findfa(x);fa2=findfa(y);
if(fa1!=fa2) printf("-1\n");
else printf("%d\n",v[x]-v[y]);
}
return 0;
}