估计要明晚才写得完,于是暂时持续更新。
所谓拓展,肯定和简单地用并查集去维护联通性不同。
较为简单的联通性问题如: http://blog.csdn.net/z635457712a/article/details/7919198
1. 维护一种相对的信息,用不规范的说法就是带权值的并查集
Lyp 的战斗记录
众所周知,我们的 lyp 神犇外号叫 Altman,的确,在另一个平行宇宙,lyp神犇就是一个——Altman。
有一天,lyp 神犇遇到了另一个平行宇宙中的他,得知了在其他的宇宙中,Altman 是存在的,那么,怪兽也是存在的咯。
作为一个有名的 oier,lyp 神犇想要统计一下各个宇宙中怪兽的战斗力,他发现,一些怪兽在不同的宇宙都出现过(!. !,难不成怪兽不穿越,算了,不管了),每一个 Altman 都提供给 lyp 一些信息,告诉他一个怪兽比另一个怪兽的战斗力大多少(这个数可以是负数)。Altman 神犇为了给你以表现机会,将这些信息都给你,并会时不时地问你两个怪兽之间谁更强。假设 Altman 们提到了怪兽都按 1~n 编号。
Altman 们的信息的格式是 X A B C
其中 x 固定为 1,A,B 是两个 1~n 的整数,表示怪兽编号,A 怪兽的战斗力比 B 怪兽的战斗力大 C(C 为整数),保证信息之间不矛盾。
Lyp 的询问的格式是:Y A B
Y 固定为 2,A,B 是怪兽编号,属于 1~n,如果 A 比 B 强,输出 A;如果 B比 A 强,输出 B,如果无法判断或怪兽们一样强,输出 0
【输入格式】: 第 1 行,两个数 n,q,n 表示怪兽总数,q 表示询问与信息的总数;
第 2~q+1 行, 每一行是一个信息或询问,格式如题;
【输出格式】: 对于每一个询问,用单独一行回答。
【样例】:
Input
3 3
1 1 2 3
1 3 2 1
2 1 3
Output
1
【数据约定】: 30% n<=100 q<=300
100% n<=30000 q<=50000
c 的绝对值不超过 5000
这类题有种类似向量加法的感觉,一直A -> B, B -> C, 就可以推知A -> C。
code
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn = 30000 + 5;
//class union_find_set
typedef int INT[maxn];
int n, q;
INT w, ufs;
int find(int u)
{
if (u != ufs[u])
{
int f = find(ufs[u]);
w[u] += w[ufs[u]];
ufs[u] = f;
}
return ufs[u];
}
int main()
{
freopen("lyp.in", "r", stdin);
freopen("lyp.out", "w", stdout);
cin >> n >> q;
for (; n; --n) ufs[n] = n;
for (; q; --q)
{
int ch;
scanf("%d", &ch);
switch (ch)
{
int x, y, z, fi, fj;
case 1 :
scanf("%d%d%d", &x, &y, &z);
fi = find(x), fj = find(y);
w[fi] = z - (w[x] - w[y]);
ufs[fi] = fj;
break;
case 2 :
scanf("%d%d", &x, &y);
fi = find(x), fj = find(y);
if (fi != fj) cout << "0" << endl;
else if (w[x] > w[y]) cout << x << endl;
else if (w[x] < w[y]) cout << y << endl;
else if (w[x] == w[y]) cout << "0" << endl;
break;
}
}
return 0;
}