并查集基本框架使用
初始化
查找并查集,不相同就更新根接点
合并并查集
import sys
sys.setrecursionlimit(600000)
from collections import deque
#collections.deque.
def init_set(): # 并查集的初始化
for i in range(N):
s.append(i)
def find_set(x):
if (x!=s[x]):
s[x] = find_set(s[x]) # 递归查找根节点同时更新更节点
return s[x]
def merge(x,y): # 合并并查集
x = find_set(x)
y = find_set(y)
if x!=y:
s[x]=s[y]
n,m = map(int,input().split())
s = [] # 并查集
N=800000
init_set()
for i in range(m): # 行
op,x,y = map(int,input().split())
if op==1:
merge(x,y) # 合并并查集
if op==2:
if(find_set(x) == find_set(y)): print("YES")
else: print("NO")
并查集的一种简易判断方法(合根数量,每次合并减一即可)
import sys
sys.setrecursionlimit(600000)
from collections import deque
#collections.deque.
def init_set(): # 并查集的初始化
for i in range(N):
s.append(i)
def find_set(x):
if (x!=s[x]):
s[x] = find_set(s[x]) # 递归查找根节点同时更新更节点
return s[x]
def merge(x,y): # 合并并查集
x = find_set(x)
y = find_set(y)
if x!=y: # 合根
s[y]=s[x]
return True
else: return False # 相等说明合根过一次
m,n = map(int,input().split())
s = [] # 并查集
N=800000
init_set()
k = int(input())
ans = n*m # 发现一个合根就减一
for i in range(k): # 行
x,y = map(int,input().split())
if(merge(x,y)):
ans-=1
print(ans)
暴力|哈希|并查集 三种方法
import os
import sys
# 暴力法1 30%
# n = int(input())
# a = [int(i) for i in input().split()] #将输入的转为矩阵
# for i in range(1,n): # 1---n-1 从第二个开始 a[0],a[1],a[2],a[3].........
# for j in range(i): # 从 0--i-1
# while a[i] in a[0:i] : # 后续元素在前面出现一直加1,直到不出现
# a[i]+=1
# for i in a: print(i,end=' ')
# 暴力法2 60%
# n = eval(input())
# a = [int(i) for i in input().split()]
# s = set() # 集合为哈希表存储 ,查找是否存在更快
# for i in range(n):
# while a[i] in s:
# a[i]+=1
# s.add(a[i])
# print(*a)
#并查集 100%
def find_set(x):
if (x != s[x]): s[x] = find_set(s[x])
return s[x]
def init_set():
for i in range(800000):
s.append(i)
s=[] # 并查集
init_set()
n = int(input())
a = [int(i) for i in input().split()]
for i in range(n):
root = find_set(a[i]) # 查找并查集对应的,初始状态findset(a[i])==a[i]
a[i] = root # 将并查集中的数赋值给a[]
s[root] = find_set(root+1) # 并查集的指向加1
print(*a)
一种暴力方法(找规律)
import os
import sys
# 请在此输入您的代码
k = int(input()) # 多少个存钱罐
m =[int(input()) for _ in range(k)]
count = 0
vis = [0]*(k+1) # 不要首元素
for i in range(1,k):
if m[i]==i+1: # 钥匙在自己存钱罐
count+=1
vis[m[i]]=1 # 没出现自己的钥匙
print(vis.count(0)-1+count)
简单数论(gcd,lcm)
import sys
sys.setrecursionlimit(600000)
from collections import deque
#collections.deque.
import math
def lcm(x,y):
return x*y//math.gcd(x,y)
a,b,c = map(int,input().split())
print(lcm(lcm(a,b),c))
找最小公差(math.gcd)
import sys
sys.setrecursionlimit(600000)
from collections import deque
#collections.deque.
import math
def lac(x,y):
return x*y//math.gcd(x,y)
n = int(input())
m =[0]+ [int(x) for x in input().split()] # 读入元素
b=0
for i in range(2,n+1): # 1 - n
b=math.gcd(b,m[i]-m[i-1])
#print(b)
m.sort()
print((m[-1]-m[1])//b+1)
gcd,lcm运用(理解公倍数,公约数的意义)
import os
import sys
# 请在此输入您的代码
import math
def lcm(x,y): # 求最大公约
return x*y//math.gcd(x,y)
n = int(input())
for i in range(n):
a0,a1,b0,b1 = map(int,input().split())
ans =0 # 记录个数
for x in range(1,int(math.sqrt(b1))+1):
if b1 % x ==0: # 表示b1是x的公倍数 # 抓住公倍数这个条件
if math.gcd(x,a0)==a1 and lcm(x,b0)==b1:
ans+=1
y=b1//x
if x==y:
continue
if math.gcd(y,a0)==a1 and lcm(y,b0)==b1:
ans+=1
print(ans)
简单数论放松题
import sys
sys.setrecursionlimit(600000)
from collections import deque
#collections.deque.
import math
a,b,n = map(int,input().split())
week = a*5+b*2
day1 =7*(n//week)
left = n % week # 剩下的数量
if left<=5*a: # 前五天内可完成
day2 =left//a + (1 if left % a else 0) # 三目运算符
else: # 周末才能完成
day2 =5+(left-5*a)//b + (1 if (left-5*a)%b else 0)
print(day1+day2)