并查集,离散化
人人都是好朋友
https://www.nowcoder.com/practice/431a2726d73e424896d3fd222c2c1621
思路:看到题目中提到了传递性,并且和点、边有关,首先要想到并查集。但直接用常规的连续并查集,对于1e9的点数量来说,会爆内存,因此我们需要在创建、使用并查集之前,对数据进行离散化操作
之后就是创建并查集,然后判断c为0的情况下,a和b是否已经合并过了。如果有的话,说明存在矛盾,输出"NO";否则就合并a, b,最终合并完成都没有矛盾,直接输出"YES"即可
代码:
import sys
from bisect import bisect_left
input = lambda: sys.stdin.readline().strip()
import math
inf = 10 ** 18
def I():
return input()
def II():
return int(input())
def MII():
return map(int, input().split())
def GMI():
return map(lambda x: int(x) - 1, input().split())
def LI():
return input().split()
def LII():
return list(map(int, input().split()))
def LFI():
return list(map(float, input().split()))
fmax = lambda x, y: x if x > y else y
fmin = lambda x, y: x if x < y else y
isqrt = lambda x: int(math.sqrt(x))
'''
'''
# 模板来源 https://leetcode.cn/circle/discuss/mOr1u6/
class UnionFind:
def __init__(self, n: int):
# 一开始有 n 个集合 {0}, {1}, ..., {n-1}
# 集合 i 的代表元是自己,大小为 1
self._fa = list(range(n)) # 代表元
self._size = [1] * n # 集合大小
self.cc = n # 连通块个数
# 返回 x 所在集合的代表元
# 同时做路径压缩,也就是把 x 所在集合中的所有元素的 fa 都改成代表元
def find(self, x: int) -> int:
fa = self._fa
# 如果 fa[x] == x,则表示 x 是代表元
if fa[x] != x:
fa[x] = self.find(fa[x]) # fa 改成代表元
return fa[x]
# 判断 x 和 y 是否在同一个集合
def is_same(self, x: int, y: int) -> bool:
# 如果 x 的代表元和 y 的代表元相同,那么 x 和 y 就在同一个集合
# 这就是代表元的作用:用来快速判断两个元素是否在同一个集合
return self.find(x) == self.find(y)
# 把 from 所在集合合并到 to 所在集合中
# 返回是否合并成功
def merge(self, from_: int, to: int) -> bool:
x, y = self.find(from_), self.find(to)
if x == y: # from 和 to 在同一个集合,不做合并
return False
self._fa[x] = y # 合并集合。修改后就可以认为 from 和 to 在同一个集合了
self._size[y] += self._size[x] # 更新集合大小(注意集合大小保存在代表元上)
# 无需更新 _size[x],因为我们不用 _size[x] 而是用 _size[find(x)] 获取集合大小,但 find(x) == y,我们不会再访问 _size[x]
self.cc -= 1 # 成功合并,连通块个数减一
return True
# 返回 x 所在集合的大小
def get_size(self, x: int) -> int:
return self._size[self.find(x)] # 集合大小保存在代表元上
def solve():
n = II()
edges = []
nodes = set()
for _ in range(n):
a, b, c = LII()
edges.append((a, b, c))
nodes.add(a)
nodes.add(b)
nodes = sorted(nodes)
m = len(nodes)
uf = UnionFind(m)
for a, b, c in edges:
ia = bisect_left(nodes, a)
ib = bisect_left(nodes, b)
if c == 0 and uf.is_same(ia, ib):
print("NO")
return
uf.merge(ia, ib)
print("YES")
# t = 1
t = II()
for _ in range(t):
solve()
#每日一题挑战#