【[Offer收割]编程练习赛15 B】分数调查

【题目链接】:http://hihocoder.com/problemset/problem/1515

【题意】

【题解】

带权并查集
relation[x]表示父亲节点比当前节点大多少;
对于输入的x,y,z;
如果z小于0;
则交换x,y同时z取相反数;
然后按照带权并查集的更新方式,对y的根节点的r2的relation[r2]进行更新即可;

【Number Of WA

0

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,1,0,-1,0,-1,-1,1,1};
const int dy[9] = {0,0,-1,0,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 100000+100;
const int INF = 0x3f3f3f3f;

int n,m,q,f[N],relation[N];

int ff(int x)
{
    if (f[x] == x)
        return x;
    int olfa = f[x];
    f[x] = ff(f[x]);
    relation[x] = relation[x] + relation[olfa];
    return f[x];
}

int main()
{
    //freopen("D:\rush.txt","r",stdin);
    ios::sync_with_stdio(false),cin.tie(0);//scanf,puts,printf not use
    cin >> n >> m >> q;
    rep1(i,1,n)
        f[i] = i,relation[i] = 0;
    rep1(i,1,m)
    {
        int x,y,z;
        cin >> x >> y >> z;
        if (z<0)
        {
            swap(x,y);
            z = -z;
        }
        int r1 = ff(x),r2 = ff(y);
        if (r1!=r2)
        {
            f[r2] = r1;
            relation[r2] = z+relation[x]-relation[y];
        }
    }
    rep1(i,1,q)
    {
        int x,y;
        cin >> x >> y;
        int r1 = ff(x),r2 = ff(y);
        if (r1!=r2)
            cout << -1 << endl;
        else
        {
            int temp = relation[y]-relation[x];
            cout << temp << endl;
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/AWCXV/p/7626383.html