結果
| 問題 | No.317 辺の追加 |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2016-02-29 19:12:15 |
| 言語 | Python3 (3.13.1 + numpy 2.2.1 + scipy 1.14.1) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 2,233 bytes |
| 記録 | |
| コンパイル時間 | 309 ms |
| コンパイル使用メモリ | 12,928 KB |
| 実行使用メモリ | 25,508 KB |
| 最終ジャッジ日時 | 2024-09-24 12:51:47 |
| 合計ジャッジ時間 | 10,007 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | WA * 6 TLE * 1 -- * 31 |
ソースコード
class DisjointSet(object):
def __init__(self, n):
self.parent = list(range(n))
self.rank = [0] * n
self.num = n # number of disjoint sets
def union(self, x, y):
self._link(self.find_set(x), self.find_set(y))
def _link(self, x, y):
if x == y:
return
self.num -= 1
if self.rank[x] > self.rank[y]:
self.parent[y] = x
else:
self.parent[x] = y
if self.rank[x] == self.rank[y]:
self.rank[y] += 1
def find_set(self, x):
xp = self.parent[x]
if xp != x:
self.parent[x] = self.find_set(xp)
return self.parent[x]
def read_data():
N, M = map(int, input().split())
ds = DisjointSet(N)
for m in range(M):
u, v = map(int, input().split())
u -= 1
v -= 1
if u == v:
continue
ds.union(u, v)
return N, ds
def solve2(N, ds):
counts = [0] * N
for i in range(N):
counts[ds.find_set(i)] += 1
freqs = [0] * (N + 1)
for c in counts:
freqs[c] += 1
vs = []
ms = []
for i, f in enumerate(freqs):
if f and i:
vs.append(i)
ms.append(f)
dp = solve_min_coins(vs, ms, N)
for w in dp[1:]:
print(w - 1)
def solve_min_coins(vs, ms, N):
'''
len(vs) 種類のコインがある。
コインの額面は vs[i], コインの枚数は ms[i]
sum(v * m for v, m in zip(vs, ms)) == N <= 10**5
が成り立つ。
1 から N 円までの各金額をコインであらわすとき、各金額における最小コイン枚数はいくつか?
'''
dp = [0] * (N + 1)
for v, m in zip(vs, ms):
update_dp(v, m, dp, N)
return dp
def update_dp(v, m, dp, N):
pow2 = 1
while pow2 <= m:
if m & pow2:
update_dp_core(v * pow2, pow2, dp, N)
pow2 <<= 1
def update_dp_core(v, w, dp, N):
for i in range(N - v, 0, -1):
if dp[i]:
dpiv = dp[i + v]
if dp[i] + w < dpiv or dpiv == 0:
dp[i + v] = dp[i] + w
if dp[v] > w or dp[v] == 0:
dp[v] = w
N, ds = read_data()
solve2(N, ds)