# 带权并查集

int find(int x)
{
if (x != parent[x])
{
parent[x] = find(parent[x]);
}
return parent[x];
}

1.每个节点都记录的是与根节点之间的权值，那么在Find的路径压缩过程中，权值也应该做相应的更新，因为在路径压缩之前，每个节点都是与其父节点链接着，那个Value自然也是与其父节点之间的权值

2.在两个并查集做合并的时候，权值也要做相应的更新，因为两个并查集的根节点不同。

int find(int x)
{
if (x != parent[x])
{
int t = parent[x];
parent[x] = find(parent[x]);
value[x] += value[t];
}
return parent[x];
}

		int px = find(x);
int py = find(y);
if (px != py)
{
parent[px] = py;
value[px] = -value[x] + value[y] + s;
}

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <stdio.h>
using namespace std;

const int maxM = 200005;
int parent[maxM];
int sum[maxM];

int Find(int x)
{
if (x != parent[x])
{
int i = parent[x];
parent[x] = Find(parent[x]);
sum[x] += sum[i];
}
return parent[x];
}

int main()
{
int m, n;
int ans = 0;
while (scanf("%d%d", &m, &n) != EOF)
{
for (int i = 0; i <= m; i++)
{
parent[i] = i;
sum[i] = 0;
}
ans = 0;
while (n--)
{
int l, r, value;
cin >> l >> r >> value;
l--;
int fl = Find(l);
int fr = Find(r);
if (fl == fr)
{
if ((sum[l] - sum[r]) != value)
{
ans++;
}
}
else {
parent[fl] = fr;
sum[fl] = -sum[l] + sum[r] + value;
}
}
cout << ans << endl;
}
return 0;
}


HihoCoder-1515-分数调查

### 输出

10 5 3
1 2 10
2 3 10
4 5 -10
5 6 -10
2 5 10
1 10
1 5
3 5

-1
20
0

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
const int maxN = 100005;
int parent[maxN];
int score[maxN];

int find(int x)
{
if (x != parent[x])
{
int t = parent[x];
parent[x] = find(parent[x]);
score[x] += score[t];
}
return parent[x];
}
int main()
{
int n, m, q;
scanf("%d%d%d", &n, &m, &q);
for (int i = 1 ; i <= n ; i ++ )
{
parent[i] = i;
}
while ( m-- )
{
int x, y, s;
scanf("%d%d%d", &x, &y, &s);
int px = find(x);
int py = find(y);
if (px != py)
{
parent[px] = py;
score[px] = -score[x] + score[y] + s;
}
}
while ( q -- )
{
int x, y;
scanf("%d%d",&x,&y);
if (find(x) != find(y))
{
printf("-1\n");
}
else {
printf("%d\n", score[x] - score[y]);
}
}

return 0;
}

poj-1182-食物链

 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 92490 Accepted: 27910

Description

1） 当前的话与前面的某些真的话冲突，就是假话；
2） 当前的话中X或Y比N大，就是假话；
3） 当前的话表示X吃X，就是假话。

Input

Output

Sample Input

100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5


Sample Output

3

1.路径压缩时，如何更新Value

2.区间合并时，如何更新Value

relationWithParent[fx] = (-relationWithParent[x] + relation + relationWithParent[y]) % 3

3.如何判断是否矛盾

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <stdio.h>
using namespace std;
const int maxN = 50005;

int parent[maxN];
int relationWithParent[maxN];    // 0 ： 同类 1：吃 2：被吃

// A吃B B吃C ==> A被C吃     Relation(a,c) = Relation(a,b)+Relation(b,c)
// A被B吃 B被C吃 ==> A吃C Relation(a,c) = (Relation(a,b)+Relation(b,c))%3
int find(int x )
{
if ( x != parent[x])
{
int t = parent[x];
parent[x] = find(parent[x]);
relationWithParent[x] = (relationWithParent[x] + relationWithParent[t]) % 3;
}
return parent[x];
}

int main()
{
int n, k;

cin >> n >> k;
int ans = 0;
for (int i = 1 ; i <= n ; i ++ )
{
parent[i] = i;
}
while (k--)
{
int relation, x, y;
scanf("%d%d%d",&relation,&x,&y);
if ( x > n || y > n || (relation == 2 && x == y ) )
{
ans++;
}
else {
int fx = find(x);
int fy = find(y);
if (fx == fy)
{
if ((relation - 1) != ((relationWithParent[x] - relationWithParent[y] + 3) % 3))
ans++;
}
else {
parent[fx] = fy;
relationWithParent[fx] = (-relationWithParent[x] + relation  - 1 + relationWithParent[y]) % 3;
}
}
}
cout << ans;
return 0;
}

08-11 1万+
03-26 8644

06-06 7459
07-08 8576
08-07 432
10-12 277
08-08 1388
07-07 208
07-29 7989
06-09 1万+
07-08 189
06-11 701
04-29 462
05-20 800
08-28 125
08-16 1981