diff --git "a/05\354\233\224 31\354\235\274 - \354\265\234\354\206\214 \354\213\240\354\236\245 \355\212\270\353\246\254/1244.py" "b/05\354\233\224 31\354\235\274 - \354\265\234\354\206\214 \354\213\240\354\236\245 \355\212\270\353\246\254/1244.py" new file mode 100644 index 0000000..cf0d9fe --- /dev/null +++ "b/05\354\233\224 31\354\235\274 - \354\265\234\354\206\214 \354\213\240\354\236\245 \355\212\270\353\246\254/1244.py" @@ -0,0 +1,46 @@ +import sys #sys 모듈 +input = sys.stdin.readline #입출력 향상 코드 + +""" +[스위치 켜고 끄기] + + 남학생 -> 해당 번호의 배수에 해당하는 스위치 상태 바꾸기 + 여학생 -> 해당 번호를 중심으로 좌우 대칭이면서 가장 많은 스위치 포함하는 구간의 상태 모두 바꾸기 + + 좌우 대칭 검사 시, 스위치 범위 주의 (주어진 스위치 범위 넘어가지 않도록) + 스위치 20개씩 출력하는 부분 주의 + 인덱스 번호 주의 +""" + +# 남학생의 스위치 바꾸기 +def change_switch_boy(k, n, switch): + # k-1 부터 -> 인덱스는 0부터니까 + for i in range(k-1, n, k): #k의 배수 스위치 + switch[i] = 1 - switch[i] #스위치 상태 바꾸기 + return + +# 여학생의 스위치 바꾸기 +def change_switch_girl(k, n, switch): + k -= 1 # 인덱스는 0부터 + idx = 0 # 대칭 구간 + # 스위치 범위가 넘어가거나 좌우 대칭이 깨질 때가지 + while k-idx >= 0 and k+idx < n and switch[k-idx] == switch[k+idx]: #스위치 범위 안이고 스위치가 대칭이면 + switch[k-idx] = switch[k+idx] = 1 - switch[k+idx] #스위치 상태 바꾸기 + idx += 1 #다음 대칭으로 + return + +# 입력 +n = int(input()) #스위치 개수 +switch = list(map(int, input().split())) #스위치 정보 +k = int(input()) #성별 정보 개수 + +for _ in range(k): #k번 반복 + a, b = map(int, input().split()) #성별, 스위치 번호 + if a == 1: #남자면 + change_switch_boy(b, n, switch) #남학생의 스위치 바꾸기 + else: #여자면 + change_switch_girl(b, n, switch) #여학생의 스위치 바꾸기 + +# 출력 +for i in range(0, n, 20): #스위치 20개 단위로 + print(*switch[i:i+20]) #출력하기 \ No newline at end of file diff --git "a/05\354\233\224 31\354\235\274 - \354\265\234\354\206\214 \354\213\240\354\236\245 \355\212\270\353\246\254/16202.py" "b/05\354\233\224 31\354\235\274 - \354\265\234\354\206\214 \354\213\240\354\236\245 \355\212\270\353\246\254/16202.py" new file mode 100644 index 0000000..e29743a --- /dev/null +++ "b/05\354\233\224 31\354\235\274 - \354\265\234\354\206\214 \354\213\240\354\236\245 \355\212\270\353\246\254/16202.py" @@ -0,0 +1,78 @@ +import sys #sys 모듈 +input = sys.stdin.readline #입출력 향상 코드 + +""" +[MST 게임] + + MST 알고리즘을 여러 번 실행해도 될까? + 1. 크루스칼 알고리즘의 시간 복잡도는 O(ElogE) + 이는 오직 간선을 정렬하는 연산의 시간 복잡도! + 즉, 모든 간선을 한 번 정렬해서 저장해두면 이후 몇 번의 알고리즘을 수행하여도 연산 시간에 큰 영향이 없음 + 2. 간선 재사용을 위해 우선순위 큐가 아닌 배열에 저장하고 크루스칼 알고리즘 k번 실행 + 3. 매번 크루스칼을 수행할 때마다 제일 먼저 추가한 간선을 제외함 + -> 첫번째 간선은 모든 점이 분리된 상태에서 들어오기 때문에 무조건 사용하게 되어 있고, 이는 사용한 간선 중 가장 짧은 간선 + -> 제외될 간선은 배열의 첫번째 간선부터 순차적 제외 + 4. 만약 한 번 MST를 만들 수 없다는게 확인됐다면 이후에도 MST를 만들 수 없음 +""" + +# find 연산 +def find_parent(x): + if parent[x] < 0: #x가 루트 노드면 + return x #x 반환 + + parent[x] = find_parent(parent[x]) #루트 노드 찾아서 parent[x]에 대입 + return parent[x] #parent[x] 반환 + +# union 연산 +def union(x, y): + px = find_parent(x) #x의 부모 노드 찾아서 대입 + py = find_parent(y) #y의 부모 노드 찾아서 대입 + + if px == py: #동일한 루트 노드면 + return False #합칠 수 없음 + + if parent[px] < parent[py]: #py가 더 적은 자식 노드 가지면 + parent[px] += parent[py] #py를 px에 합침 + parent[py] = px #py의 부모노드를 px로 변경 + else: #아니면 + parent[py] += parent[px] #px를 py에 합침 + parent[px] = py #px의 부모노드를 px로 변경 + + return True #합칠 수 있음 + +#크루스칼 +def kruskal(n, m, edge, turn): + cost = 0 #비용 + cnt = 0 #연결 횟수 + for w in range(turn, m+1): + u, v = edge[w] #u,v정보를 edge[w]에서 받아옴 + if not union(u, v): #합칠 수 없으면 + continue #다음 반복문으로 + + cost += w #w를 cost에 더함 + cnt += 1 #cnt 증가 + + if cnt == n-1: #n-1회 반복했으면 + return cost #cost 반환 + + return 0 #0 반환 + +n, m, k = map(int, input().split()) #정점의 수, 간선의 수, 턴 수 + +edge = [None] + [tuple(map(int, input().split())) for _ in range(m)] #간선 정보 + +result = [] #결과 리스트 + +for turn in range(1, k+1): #k번 반복 + # 초기화 + parent = [-1]*(n+1) + # 연산 + result.append(kruskal(n, m, edge, turn)) + + if result[-1] == 0: # 이후의 턴은 모두 0점이므로 + break #반복문 종료 + +result += [0]*(k-len(result)) #이후 턴들의 점수 저장 + +# 출력 +print(*result) \ No newline at end of file diff --git "a/05\354\233\224 31\354\235\274 - \354\265\234\354\206\214 \354\213\240\354\236\245 \355\212\270\353\246\254/1647.py" "b/05\354\233\224 31\354\235\274 - \354\265\234\354\206\214 \354\213\240\354\236\245 \355\212\270\353\246\254/1647.py" new file mode 100644 index 0000000..e728c9a --- /dev/null +++ "b/05\354\233\224 31\354\235\274 - \354\265\234\354\206\214 \354\213\240\354\236\245 \355\212\270\353\246\254/1647.py" @@ -0,0 +1,67 @@ +import sys #sys 모듈 +input = sys.stdin.readline #입출력 향상 코드 + +""" +[도시 분할 계획] + +마을을 두개로 분리하고, 각 집끼리 이동할 수 있는 최소한의 도로만 남기는 문제 +즉, 2개의 최소신장트리를 만들어야 하는 문제 +-> 하나의 최소신장트리를 만들고, 그 중 가장 유지비가 큰 도로를 삭제 +-> 크루스칼 알고리즘에서 가장 마지막에 삭제되는 도로가 유지비가 가장 큼 +-> 크루스칼 알고리즘에서 간선을 n-2개만 선택하여 그 합을 구하여 해결 +""" + +# find 연산 +def find_parent(x): + if parent[x] < 0: #x가 루트 노드면 + return x #x 반환 + + parent[x] = find_parent(parent[x]) #루트 노드 찾아서 parent[x]에 대입 + return parent[x] #parent[x] 반환 + +# union 연산 +def union(x, y): + px = find_parent(x) #x의 부모 노드 찾아서 대입 + py = find_parent(y) #y의 부모 노드 찾아서 대입 + + if px == py: #동일한 루트 노드면 + return False #합칠 수 없음 + + if parent[px] < parent[py]: #py가 더 적은 자식 노드 가지면 + parent[px] += parent[py] #py를 px에 합침 + parent[py] = px #py의 부모노드를 px로 변경 + else: #아니면 + parent[py] += parent[px] #px를 py에 합침 + parent[px] = py #px의 부모노드를 px로 변경 + + return True #합칠 수 있음 + +#크루스칼 +def kruskal(n, edge): + cost = 0 #비용 + cnt = 0 #횟수 + for u, v, w in edge: #edge에서 u,v,w 가져옴 + if not union(u, v): #합칠 수 없으면 + continue #다음 반복문으로 + + #합칠 수 있으면 + cost += w #w를 cost에 더하기 + cnt += 1 #cnt 증가 + + if cnt == n-1: #n-1회 수행시 + return cost #cost 반환 + + return 0 #0 반환 + +#입력 +n, m = map(int, input().split()) #집의 개수, 길의 개수 + +edge = [tuple(map(int, input().split())) for _ in range(m)] #(A,B,C) + +# 초기화 +parent = [-1]*(n+1) + +edge.sort(key=lambda x:x[2]) # 정렬 + +# 연산 & 출력 +print(kruskal(n-1, edge)) \ No newline at end of file diff --git "a/05\354\233\224 31\354\235\274 - \354\265\234\354\206\214 \354\213\240\354\236\245 \355\212\270\353\246\254/1774.py" "b/05\354\233\224 31\354\235\274 - \354\265\234\354\206\214 \354\213\240\354\236\245 \355\212\270\353\246\254/1774.py" new file mode 100644 index 0000000..5410fbf --- /dev/null +++ "b/05\354\233\224 31\354\235\274 - \354\265\234\354\206\214 \354\213\240\354\236\245 \355\212\270\353\246\254/1774.py" @@ -0,0 +1,85 @@ +import sys #sys 모듈 +input = sys.stdin.readline #입출력 향상 코드 + +""" +[우주신과의 교감] + +4386번 : 별자리 만들기의 응용 문제 + 이미 연결된 정점들이 존재한다는 것을 제외하고는 4386번과 동일 + + 1. 임의의 두 별에 대한 거리(간선) 모두 구하기 + 2. 이미 존재하는 통로들 표시 + !주의! 통로의 개수가 m개라면 v-m-1개의 간선만 더 추가하면 될까? + 이미 연결된 통로들도 사이클을 이룰 수 있기 때문에 유니온 연산을 하며 사이클 없이 연결된 간선만 세기 + 3. 이미 연결된 통로의 수를 k개라고 하면 v-k-1개의 간선을 추가로 선택 +""" + +# find 연산 +def find_parent(x): + if parent[x] < 0: #x가 루트 노드면 + return x #x 반환 + + parent[x] = find_parent(parent[x]) #루트 노드 찾아서 parent[x]에 대입 + return parent[x] #parent[x] 반환 + +# union 연산 +def union(x, y): + px = find_parent(x) #x의 부모 노드 찾아서 대입 + py = find_parent(y) #y의 부모 노드 찾아서 대입 + + if px == py: #동일한 루트 노드면 + return False #합칠 수 없음 + + if parent[px] < parent[py]: #py가 더 적은 자식 노드 가지면 + parent[px] += parent[py] #py를 px에 합침 + parent[py] = px #py의 부모노드를 px로 변경 + else: #아니면 + parent[py] += parent[px] #px를 py에 합침 + parent[px] = py #px의 부모노드를 px로 변경 + + return True #합칠 수 있음 + +#크루스칼 +def kruskal(n, edge): + cost = 0 #비용 + cnt = 0 #횟수 + for u, v, w in edge: #edge에서 u,v,w 가져옴 + if not union(u, v): #합칠 수 없으면 + continue #다음 반복문으로 + + #합칠 수 있으면 + cost += w #w를 cost에 더하기 + cnt += 1 #cnt 증가 + + if cnt == n-1: #n-1회 수행시 + return cost #cost 반환 + + return 0 #0 반환 + +# 입력 +n, m = map(int, input().split()) #우주신 개수, 통로 개수 +position = [tuple(map(int, input().split())) for _ in range(n)] #좌표 +edge = [] #통로의 길이 저장하는 리스트 + +for i in range(n): + for j in range(i): + dx = position[i][0] - position[j][0] #x좌표 차이 계산 + dy = position[i][1] - position[j][1] #y좌표 차이 계산 + + edge.append((i, j, (dx**2 + dy**2)**(1/2))) #통로 쌍과 길이 edge에 저장 + +# 초기화 +parent = [-1]*(n) + +cnt = 0 #연결 횟수 + +for _ in range(m): #이미 연결된 통로 정보 + u, v = map(int, input().split()) #입력 받음 + # 이미 연결한 통로 + if union(u-1, v-1): #연결할 수 있으면 + cnt += 1 #cnt 증가 + +edge.sort(key=lambda x:x[2]) # 정렬 + +# 연산 & 출력 +print("%.2f" %(kruskal(n - cnt, edge))) \ No newline at end of file