题意:
有n学生,告诉你m条消息,每天消息为a比b高s分
q此询问,问两个学生的分数差,不能得出则-1
解析:
在并查集的基础上,我们用一个数组v来记录点于其现在的根结点的差,v[2]==10表示二比二的根高10
在findfa和unit函数进行的同时更新v就行
- findfa时,同递归的方法,用其父结点的v推出其v
- unit时,连接两个点的根,
f1=fi(a),f2=fi(b);fa[f1]=f2;v[f1]=s+v[b]-v[a]
在最后计算的时候,假设有相同根,那么用他们和根的差相减即可
代码:
#include<stdio.h>
#include<iostream>
using namespace std;
#define D long long
D read(){ D ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
const int maxn = 100009;
int fa[maxn],v[maxn];
int fi(int a){
if(fa[a]==a)return a;
int tmp=fa[a];
fa[a]=fi(fa[a]);
v[a]+=v[tmp];
return fa[a];
}
int un(int a,int b,int s){//返回1表示矛盾
int f1=fi(a),f2=fi(b);
if(f1==f2){
if(s+v[b]==v[a])return 0;
return 1;
}
fa[f1]=f2;v[f1]=s+v[b]-v[a];
return 0;
}
int main(){
int n=read();
for(int i=1;i<=n;i++)fa[i]=i,v[i]=0;//v[2]=10表示 c[2]-c[fi(2)]=10
int m=read();
int q=read();
while(m--){
int a,b,s;scanf("%d%d%d",&a,&b,&s);//a-b=s
un(a,b,s);
}
while(q--){
int a,b;scanf("%d%d",&a,&b);//a-b=?
if(fi(a)!=fi(b))printf("-1\n");
else printf("%d\n",v[a]-v[b]);
}
}