How Many Answers Are Wrong https://vjudge.net/problem/HDU-3038#author=hzoi2017_nzy
加权并查集简单应用,难点是想到用加权并查集来解决这个问题,和计算权值。
计算方法
图是鼠标画的,凑活看看。
我们将y并入x,只需要计算d[y]的值,其所有子结点会在find时自动更新,d[y]表示从y到x的距离,b到a的距离为num,则b到x距离为d[a]+num,即为图中红色部分,b到y距离为d[b],所以,y到x的距离d[y]为d[a]+num-d[b];代码中num用c来表示。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <sstream>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <vector>
#include <stack>
#define sc(n) scanf("%d", &n)
const int N = 1e5 + 10;
#define int long long
#define endl '\n'
#define FAST ios::sync_with_stdio(false);
using namespace std;
int p[N], d[N];
int n, m, ans = 0;
void init()//初始化
{
for (int i = 1; i <= n; i++)
p[i] = i, d[i] = 0;
ans=0;
}
int find(int x)
{
if (x != p[x])
{
int t = find(p[x]);
d[x] += d[p[x]];
p[x] = t;
}
return p[x];
}
void merge(int a, int b, int c)
{
int x = find(a) , y = find(b);
if (x == y)
{
if (d[b] != d[a] + c)
ans++;
}
else
{
p[y]=x;
d[x]=d[a]+c-d[b];
}
}
void solve()
{
while (cin >> n >> m)// 本题为多组输入
{
init();
for (int i = 1; i <= m; i++)
{
int a,b,c;
cin>>a>>b>>c;
merge(a,b,c);
}
cout<<ans<<endl;
}
}
signed main()
{
FAST;
int _;
// cin >> _;
_ = 1;
while (_--)
solve();
return 0;
}