带权并查集是权值并查集的分支,对这个题而言,我们要将人分成两部分,保证每一部分的内部的边的最大权值尽可能的小,从贪心的角度考虑,我们肯定是从大权值向小权值遍历,尽可能的将大权值的端点分离,当遇到第一个,必须得在一部分的边就是答案。那么我们如何理解这个带权并查集呢
开两倍空间,1~n是a监狱,n+1~2*n是b监狱
遍历边时我们先看端点x,y是不是已经在同一监狱了,如果不在,那么有两种可能,第一就是x在a监狱,y在b监狱,相连;然后反之再连一次。
n,m=map(int ,input().split())
class node :
def __init__(self,u,v,t):
self.v=v
self.u=u
self.t=t
def __lt__(self, other):
return self.t>other.t
mp=[]
vis=[i for i in range(40010)]
for i in range(m):
a,b,c=map(int ,input().split())
mp.append(node(a,b,c))
mp.sort()
def find(x):
if (vis[x]==x): return x
vis[x]=find(vis[x])
return vis[x]
vv=0
for i in mp:
if (find(i.u)==find(i.v) or find(i.u+n)==find(i.v+n)):
print(i.t)
vv=1
break
vis[vis[i.v]]=vis[i.u+n]
vis[vis[i.v+n]]=vis[i.u]
if (vv==0) :print(0)
这个题要读明白题意,就是a是b的天敌,c是a的天敌,能推导出c是b的猎物。
分成三部分 同类 天敌 猎物 开三倍空间 剩下的看下注释
n,k=map(int ,input().split())
vis=[i for i in range(50000*3+100)] #tonglei tiandi liewu
def find(x):
if (x==vis[x]):return x
vis[x]=find(vis[x])
return vis[x]
ans=0
for i in range(k):
opt,x,y=map(int ,input().split())
if (x>n or y>n):
ans+=1
continue
if (opt==1):
#如果x是y的天敌 或 x是y的猎物 这就是假的
if (find(x)==find(y+n) or find(x)==find(y+2*n)):ans+=1
else :
#x和y是同一类 所以同类合并,天敌合并,猎物也合并
vis[find(x)]=vis[find(y)]
vis[find(x+n)]=vis[y+n]
vis[find(x+2*n)]=vis[y+2*n]
else:
#如果x和y是同类 或 x的天敌是y 假
if (find(x)==find(y) or find(x+n)==find(y)): ans+=1
else :
vis[find(y+n)]=vis[x] #y的天敌是x
vis[find(x+2*n)]=vis[y] #x的猎物是y
vis[find(y+2*n)]=vis[x+n] #y的猎物是x的天敌
print(ans)