分数调查 HihoCoder - 1515

小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

题解:带权并查集,只需要每个节点找出与根节点相差几分就可以了
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<stack>
#include<map>
#include<cstdlib>
#include<vector>
#include<string>
#include<queue>
using namespace std;

#define ll long long
#define llu unsigned long long
#define INF 0x3f3f3f3f
const double PI = acos(-1.0);
const int maxn =  1e5+10;
const int mod = 1e9+7;

struct node
{
    int pre;
    int ans;
}p[maxn];

int find(int x)
{
    int temp;
    if(x == p[x].pre)
        return x;
    temp = p[x].pre;
    p[x].pre = find(temp);
    p[x].ans = p[x].ans + p[temp].ans;
    return p[x].pre;
}
void combine(int x,int y,int num)
{
    int prex = find(x);
    int prey = find(y);
    if(prex != prey)
    {
        p[prex].pre = prey;
        p[prex].ans = p[y].ans -p[x].ans + num;
    }
}
int main()
{
   int n,m,q;
   scanf("%d %d %d",&n,&m,&q);
   for(int i=1;i<=n;i++)
   {
       p[i].pre = i;
       p[i].ans = 0;
   }
   for(int i=0;i<m;i++)
   {
       int a,b,num;
       scanf("%d %d %d",&a,&b,&num);
       combine(a,b,num);
   }
   for(int i=0;i<q;i++)
   {
       int a,b;
       scanf("%d %d",&a,&b);
       if(find(a) != find(b))
           printf("-1\n");
       else
       {
           printf("%d\n",p[a].ans - p[b].ans);
       }
   }
}
View Code

 

posted @ 2019-01-28 18:18  千摆渡Qbd  阅读(221)  评论(0编辑  收藏  举报