洛谷P2294 [HNOI2005]狡猾的商人

一道差分约束.

但是我横看竖看, 只从字缝里看到了"并查集"三个大字.

很明显嘛, 什么判断真假, 什么前缀和关系传递, 不是明摆着的带权并查集吗?

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1e2 + 10;
const int MAXM = 1e3 + 10;

int W, N, M;

namespace ufs
{
    int fa[MAXM], d[MAXM];

    void init(){
        memset(d, 0, sizeof(d));
        for(int i = 0; i <= N; i++) fa[i] = i;
    }

    int findfa(int x){
        if(fa[x] == x) return x;

        int tmp = findfa(fa[x]);
        d[x] += d[fa[x]];
        return fa[x] = tmp;
    }

    inline bool unite(int u, int v, int c)
    {
        if(u > v) swap(u, v);
        int x = findfa(u), y = findfa(v);
        if(x == y) return c == (d[u] - d[v]);

        if(x < y) {
            fa[x] = y, d[x] = d[v] + c - d[u];
            return true;
        } 
        else{
            fa[y] = x, d[y] = d[u] - c - d[v];
            return true;
        }
    }
}

int main()
{
    //freopen("p2294.in", "r", stdin);
    cin>>W;
    while(W--)
    {
        cin>>N>>M;
        bool flag = true; ufs::init();
        for(int i = 1, u, v, c; i <= M; i++){
            scanf("%d%d%d", &u, &v, &c);
            if(!flag) continue;
            if(!ufs::unite(u - 1, v, c)) flag = false;
        }
        if(flag) puts("true");
        else puts("false");
    }
    return 0;
}

转载于:https://www.cnblogs.com/wsmrxc/p/9334649.html

原文地址:https://www.cnblogs.com/twodog/p/12136427.html