結果
| 問題 | No.317 辺の追加 |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-10-12 15:31:11 |
| 言語 | D (dmd 2.113.0) |
| 結果 |
WJ
不安定
(最新)
AC
(最初)
|
| 実行時間 | - |
| コード長 | 2,078 bytes |
| 記録 | |
| 最終ジャッジ日時 | 2026-10-12 15:31:28 |
|
ジャッジサーバーID (参考情報) |
judge4_1 / judge2_0 |
(要ログイン)
ソースコード
module main;
// https://mayokoex.hatenablog.com/entry/2015/12/11/162941 より
// 連結成分、動的計画法
import std;
// atcoder-library より
// 無向グラフに対して辺の追加と、頂点a,b間が連結かどうかをO(α(n))で求める
struct Dsu {
private:
int n;
int[] parentOrSize;
public:
this(int n)
{
this.n = n;
parentOrSize = [-1].replicate(n);
}
int merge(int a, int b)
{
assert(0 <= a && a < n);
assert(0 <= b && b < n);
int x = leader(a), y = leader(b);
if (x == y) return x;
if (-parentOrSize[x] < -parentOrSize[y]) swap(x, y);
parentOrSize[x] += parentOrSize[y];
parentOrSize[y] = x;
return x;
}
bool same(int a, int b)
{
assert(0 <= a && a < n);
assert(0 <= b && b < n);
return leader(a) == leader(b);
}
int leader(int a)
{
assert(0 <= a && a < n);
if (parentOrSize[a] < 0) return a;
return parentOrSize[a] = leader(parentOrSize[a]);
}
int size(int a) {
assert(0 <= a && a < n);
return -parentOrSize[leader(a)];
}
int[][] groups()
{
auto leaderBuf = iota(0, n).map!(i => leader(i)).array;
auto groupSize = new int[](n);
foreach (i; 0 .. n)
groupSize[leaderBuf[i]]++;
auto result = new int[][](n);
foreach (i; 0 .. n)
result[leaderBuf[i]] ~= i;
result = result.remove!(a => a.empty);
return result;
}
}
void main()
{
// 入力
int N, M;
readln.chomp.formattedRead("%d %d", N, M);
auto dsu = Dsu(N);
foreach (_; 0 .. M) {
int u, v;
readln.chomp.formattedRead("%d %d", u, v);
u--, v--;
if (!dsu.same(u, v)) {
dsu.merge(u, v);
}
}
// 答えの計算
auto cnt = new int[](N + 1);
foreach (g; dsu.groups) cnt[g.length]++;
immutable INF = 10 ^^ 9;
auto ans = uninitializedArray!(int[])(N + 1);
ans[] = INF;
ans[0] = 0;
foreach (i; 1 .. N + 1) {
for (int k = 1; cnt[i]; k <<= 1) {
int num = min(cnt[i], k);
foreach_reverse (j; 0 .. N - num * i + 1) {
int nj = j + num * i;
ans[nj] = min(ans[nj], ans[j] + num);
}
cnt[i] -= num;
}
}
// 答えの出力
foreach (i; 1 .. N + 1)
writeln(ans[i] == INF ? -1 : ans[i] - 1);
}