結果
| 問題 |
No.3206 う し た ウ ニ 木 あ く ん 笑
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-07-18 23:22:19 |
| 言語 | C# (.NET 8.0.404) |
| 結果 |
RE
|
| 実行時間 | - |
| コード長 | 7,921 bytes |
| コンパイル時間 | 9,769 ms |
| コンパイル使用メモリ | 169,988 KB |
| 実行使用メモリ | 284,768 KB |
| 最終ジャッジ日時 | 2025-07-18 23:23:12 |
| 合計ジャッジ時間 | 45,172 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 3 RE * 27 |
コンパイルメッセージ
復元対象のプロジェクトを決定しています... /home/judge/data/code/main.csproj を復元しました (147 ミリ秒)。 main -> /home/judge/data/code/bin/Release/net8.0/main.dll main -> /home/judge/data/code/bin/Release/net8.0/publish/
ソースコード
#nullable enable
#region
var _input = Array.Empty<string>();
var _iter = 0;
string String()
{
while (_iter >= _input.Length) (_input, _iter) = (Console.ReadLine()!.Split(' '), 0);
return _input[_iter++];
}
T I<T>() where T : IParsable<T> => T.Parse(String(), null);
#endregion
T[] Range<T>(int n, Func<T> F) => Enumerable.Range(0, n).Select(_ => F()).ToArray();
var n = I<int>();
var edges = Range(n - 1, () => (I<int>() - 1, I<int>() - 1));
var sg = new StaticGraph(edges, n, false);
var tree = Tree.TryConstruct(sg)!;
var cd = CentroidDecomposition.Build(tree);
var ll = new int[n][];
for (var level = 0; level < cd.LevelCount; level++)
{
foreach (var center in cd.Centroids[level])
{
var adjz = sg.Adjacencies(center);
ll[center] = new int[adjz.Length];
int S(int v, int prev)
{
var adji = sg.Adjacencies(v);
var res = 0;
if (prev >= 0 && cd.Levels[v] < cd.Levels[prev])
{
for (var j = 0; j < adji.Length; j++)
{
var (next, _) = adji[j];
if (next == prev) continue;
res = Math.Max(res, ll[v][j]);
}
return res + 1;
}
for (var j = 0; j < adji.Length; j++)
{
var (next, _) = adji[j];
if (next == prev) continue;
var ns = S(next, v);
if (v == center) ll[center][j] = ns;
res = Math.Max(res, ns);
}
return res + 1;
}
S(center, -1);
}
}
var ans = 0;
foreach (var a in ll)
{
Array.Sort(a);
Array.Reverse(a);
var min = int.MaxValue;
for (var i = 0; i < a.Length; i++)
{
min = Math.Min(a[i], min);
ans = Math.Max(ans, min * (i + 1) + 1);
}
}
Console.WriteLine(ans);
class StaticGraph
{
public int N { get; }
public bool Directed { get; }
public ReadOnlySpan<(int next, int edgeIndex)> Adjacencies(int of) => _adjacencyList.Span[of].Span;
public ReadOnlySpan<(int Ab, int Ad)> Edges => _edges.Span;
readonly ReadOnlyMemory<ReadOnlyMemory<(int, int)>> _adjacencyList;
readonly ReadOnlyMemory<(int Ab, int Ad)> _edges;
public StaticGraph(IReadOnlyList<(int, int)> edges, int verticals, bool directed)
{
(N, Directed) = (verticals, directed);
var al = new List<(int, int)>[verticals];
for (var i = 0; i < verticals; i++) al[i] = new();
_edges = edges.ToArray();
for (var i = 0; i < edges.Count; i++)
{
var (ab, ad) = edges[i];
al[ab].Add((ad, i));
if (!Directed) al[ad].Add((ab, i));
}
var ala = new ReadOnlyMemory<(int, int)>[verticals];
var dataMemory = new (int, int)[directed ? edges.Count : edges.Count * 2].AsMemory();
var dataSpan = dataMemory.Span;
var k = 0;
for (var i = 0; i < verticals; i++)
{
var length = al[i].Count;
for (var j = 0; j < length; j++) dataSpan[k + j] = al[i][j];
ala[i] = dataMemory.Slice(k, length);
k += length;
}
_adjacencyList = ala;
}
}
class Graph { public required StaticGraph StaticGraph { get; init; } }
partial class Tree : Graph
{
public static Tree? TryConstruct(StaticGraph graph)
{
if (graph.Directed || graph.Edges.Length + 1 != graph.N) return null;
var visited = new bool[graph.N];
int S(int v, int prev)
{
visited[v] = true;
var res = 1;
var adjacencies = graph.Adjacencies(v);
foreach (var (next, _) in adjacencies)
{
if (next == prev || visited[next]) continue;
res += S(next, v);
}
return res;
}
if (S(0, -1) < graph.N) return null;
return new Tree() { StaticGraph = graph };
}
}
class CentroidDecomposition
{
public int LevelCount { get; private init; }
// Levels[v] is the level of the tree where v is the centroid
public required int[] Levels { get; init; }
// Centroid[level] is the list of centroids at the level
public required List<int>[] Centroids { get; init; }
// Roots[level][v] is the root of the tree of the level that has v
public required int[][] Roots { get; init; }
// Depths[level][v] is the distance from the root of the tree of the level that has v
public required int[][] Depths { get; init; }
public static CentroidDecomposition Build(Tree tree)
{
var g = tree.StaticGraph;
var n = g.N;
var levels = new int[n];
for (var i = 0; i < n; i++) levels[i] = -1;
int FindCentroid(int[] subTreeSizes, int[] parents, int total, int start)
{
var centroid = -1;
int Internal(int v, int prev)
{
var size = 1;
parents[v] = prev;
var isCentroid = true;
var adjacencies = g.Adjacencies(v);
foreach (var (next, _) in adjacencies)
{
if (next == prev || levels[next] >= 0) continue;
var cs = Internal(next, v);
if (cs > (total >> 1)) isCentroid = false;
size += cs;
}
if (isCentroid && size >= total - (total >> 1)) centroid = v;
return subTreeSizes[v] = size;
}
Internal(start, -1);
return centroid;
}
var starts = new List<(int, int)>(){ (0, n) };
var levelCount = 0;
while (starts.Count > 0)
{
var subTreeSizes = new int[n];
var parents = new int[n];
var nextStarts = new List<(int, int)>();
foreach (var (start, size) in starts)
{
var centroid = FindCentroid(subTreeSizes, parents, size, start);
levels[centroid] = levelCount;
var parent = parents[centroid];
var adjacencies = g.Adjacencies(centroid);
foreach (var (next, _) in adjacencies)
{
if (levels[next] >= 0) continue;
var nextSize = subTreeSizes[next];
if (next == parent) nextSize = size - subTreeSizes[centroid];
nextStarts.Add((next, nextSize));
}
}
starts = nextStarts;
levelCount++;
}
var centroids = new List<int>[levelCount];
for (var i = 0; i < levelCount; i++) centroids[i] = new();
for (var i = 0; i < n; i++) centroids[levels[i]].Add(i);
var roots = new int[levelCount][];
var depths = new int[levelCount][];
for (var level = 0; level < levelCount; level++)
{
var rs = new int[n];
var ds = new int[n];
for (var i = 0; i < n; i++) rs[i] = ds[i] = -1;
void S(int v, int prev)
{
var (r, d) = (rs[v], ds[v] + 1);
var adjacencies = g.Adjacencies(v);
foreach (var (next, _) in adjacencies)
{
if (next == prev || levels[next] < level) continue;
(rs[next], ds[next]) = (r, d);
S(next, v);
}
}
foreach (var centroid in centroids[level])
{
rs[centroid] = centroid;
ds[centroid] = 0;
S(centroid, -1);
}
roots[level] = rs;
depths[level] = ds;
}
return new()
{
LevelCount = levelCount,
Levels = levels,
Centroids = centroids,
Roots = roots,
Depths = depths,
};
}
}