题意描述:
根据已知节点之间的分数关系(建树),算出题目要求的两个节点之间的分数差距;
主要需要解决的就是节点之间的距离记录,其他的部分套用模板即可(主要看代码中的描述即可)
解题思路:
在找根节点和合并子集(建树)的时候将该节点到根节点的距离记录下来,在最后判断如果两个节点根节点在一棵树上将其到根节点的距离相减就行(在初始化时也将其到根节点距离归0)
节点之间距离具体实现:
dis数组的实现
初始化时:dis[i]=0每节点都是自己的boss所以到根结点的距离为0;
找根节点:dis[v]=dis[v]+dis[t]到根节点的距离等于节点到父亲节点的距离 加上父亲节点到根节点的距离;
合并子集(建树):dis[t2]=d+dis[v]-dis[u];按照本来的方程应该是dis[u]+dis[t2]+(-dis[v])=d;
将其简化后就是当前的公式了;
题目:
小Hi的学校总共有N名学生,编号1-N。学校刚刚进行了一场全校的古诗文水平测验。
学校没有公布测验的成绩,所以小Hi只能得到一些小道消息,例如X号同学的分数比Y号同学的分数高S分。
小Hi想知道利用这些消息,能不能判断出某两位同学之间的分数高低?
Input
第一行包含三个整数N, M和Q。N表示学生总数,M表示小Hi知道消息的总数,Q表示小Hi想询问的数量。
以下M行每行三个整数,X, Y和S。表示X号同学的分数比Y号同学的分数高S分。
以下Q行每行两个整数,X和Y。表示小Hi想知道X号同学的分数比Y号同学的分数高几分。
对于50%的数据,1 <= N, M, Q <= 1000
对于100%的数据,1 <= N, M, Q<= 100000 1 <= X, Y <= N -1000 <= S <= 1000
数据保证没有矛盾。
Output
对于每个询问,如果不能判断出X比Y高几分输出-1。否则输出X比Y高的分数。
Sample Input
10 5 3
1 2 10
2 3 10
4 5 -10
5 6 -10
2 5 10
1 10
1 5
3 5
Sample Output
-1
20
0
AC代码:
#include<stdio.h>
int f[100005],dis[100005];//dis数组为与根节点的分数差
int n,m;
void init()
{
for(int i=1;i<=n;i++)
{
f[i] = i;
dis[i] = 0;//开始的时候自己就是自己的老板(即所谓的根节点所以距离为0)
}
}
int getf(int v)
{
if(f[v]==v)
return v;
int t=f[v];
f[v]=getf(f[v]); //dis[v]存储的是x与父亲节点的差
dis[v]=dis[v]+dis[t]; //dis[t]存储父亲与根节点的差
return f[v];
}
void merge(int v,int u,int d)
{
int t1,t2;
t1=getf(v);
t2=getf(u);
if(t1!=t2)
{
f[t2]=t1;
dis[t2]=d+dis[v]-dis[u];
}
return ;
}
int main()
{
int x,y,d,i,q;
while(scanf("%d %d %d",&n,&m,&q)!=EOF)
{
init();
for(i=1;i<=m;i++)
{
scanf("%d %d %d",&x,&y,&d);
merge(x,y,d);
}
for(int i=1;i<=q;i++)
{
scanf("%d %d",&x,&y);
if(getf(x)==getf(y))
printf("%d\n",dis[y]-dis[x]);
//在存储的时候记录的是后节点到前一节点之间的距离也就是说子节点-父节点=
//题目所给的距离刚好与题目中描绘的前节点比后面节点大相反
else
printf("-1\n");
}
}
return 0;
}