第 019 场 AtCoder Beginner Contest
D
高橋くんと木の直径
AtCoder
⌀ 1378
原题
← C→
翻译中…

Problem Statement

翻译中…

高橋くんは木の直径を求めるのに夢中です。 木とは、頂点とそれを結ぶ辺からなる構造「グラフ」の $1$ 種で、頂点の数を $N$ 個とすると、辺は $N-1$ 本あり、どの頂点も他の全ての頂点に辺で間接・直接的につながっています。

翻译中…

image

翻译中…

この問題では、辺には整数の重みがついています。2頂点の間の距離を、その2つの頂点をつなぐ辺の重みの和と定義します。

翻译中…

木の直径とは、最も離れた2つの頂点の間の距離です。

翻译中…

以下のような木を考えてみましょう。辺の側に書かれた数が、その辺の重みです。

翻译中…

image

翻译中…

この場合、頂点 $1$ と $2$ の距離は $1$、頂点 $2$ と $4$ の間の距離は $1+2=3$ となります。頂点 $3$ と $5$ の間の距離は $3+4=7$、頂点 $4$ と $5$ の間の距離も $2+1+4=7$ で、この距離がこの木の頂点の間では最大なので、木の直径は $7$ となります。

翻译中…

高橋くんは、頂点の数と $2$ 頂点間の距離の情報から、木の直径を求めることに興味が出てきました。 この問題では、あなたは木の頂点の数 $N$ を最初に与えられ、$2$ 頂点の間の距離を尋ねる質問を何回か行い、木の直径を求めます。

翻译中…

ただし、$2$ 頂点間の距離を聞く回数には制限があります。

翻译中…

制限された質問の回数以内で木の直径を求めるプログラムを書いてください。

翻译中…

入出力

翻译中…

まず,木の頂点の数 $N$ が標準入力に与えられる。

翻译中…

N

翻译中…

続いて,あなたのプログラムは何回か応答プログラムに質問をする.質問のフォーマットは以下のとおりである。

翻译中…

? a b

翻译中…

この質問で,$a,b$ 間の距離が標準入力に1行で渡される。$1 ≦ a, b ≦ N$ かつ $a≠b$ を満たしていなければならない。

翻译中…

何回か質問を行った後、あなたは木の直径を当てる。木の直径を $diameter$ とおくと、

翻译中…

! diameter

翻译中…

というフォーマットで出力する。木の直径を出力した後、あなたのプログラムは直ちに終了しなければならない。終了しなかった場合のジャッジ結果は不定である。

翻译中…

また、これら以外のフォーマットで出力した場合のジャッジ結果も不定である。

翻译中…

この問題ではテストケースごとに質問回数の上限値が設定されており、プログラムの行った質問の回数がその上限値を上回ると誤答と判定される。

翻译中…

正答かどうかは木の直径の出力で判断される。木の直径を特定し得ない質問しかしていない場合でも、直径が正しければ正答となる。

翻译中…

翻译中…

頂点 $1$ と頂点 $2$ の間の距離を質問し、$dist$ という変数で結果を受け取る例をいくつかの言語について示す。

翻译中…

ただし、ここに書かれている方法以外で入出力を行っても良い。

翻译中…

出力した後に、出力をflushしなければならないことに注意せよ。flushしなかった場合、TLEとなることがある。

翻译中…

C

翻译中…

printf("? %d %d\n", 1, 2);
fflush(stdout);
scanf("%d", &dist);

翻译中…

C++

翻译中…

cout << "? " << 1 << " " << 2 << endl;
cin >> dist;

翻译中…

Java

翻译中…

System.out.printf("? %d %d\n", 1, 2);
Scanner scanner = new Scanner(System.in);
dist = scanner.nextInt();

翻译中…

C#

翻译中…

Console.WriteLine("? {0} {1}", 1, 2);
dist = int.Parse(Console.ReadLine());

翻译中…

D

翻译中…

writeln("? ", 1, " ", 2);
stdout.flush();
dist = readln.chomp.to!int;

翻译中…

PHP

翻译中…

echo "? ", 1, " ", 2, PHP_EOL;
$dist = trim(fgets(STDIN));

翻译中…

Python

翻译中…

print "? {0} {1}".format(1, 2)
sys.stdout.flush()
dist = int(raw_input())

翻译中…

Perl

翻译中…

$|=1;
print "? ", 1, " ", 2, "\n";
$dist = <>;

翻译中…

Ruby

翻译中…

print "? ", 1, " ", 2, "\n"
STDOUT.flush
dist = gets.to_i

翻译中…

Constraints

翻译中…
  • $2 ≦ N ≦ 50$
  • $1 ≦ (それぞれの辺の重み) ≦ 10^6$
翻译中…

部分点

翻译中…

この問題には部分点が設定されている。

翻译中…
  • $20$ 点分のテストケースにおいて、質問回数の上限値は 1300 回である。
  • 別の $80$ 点分のテストケースにおいて、質問回数の上限値は 100 回である。
翻译中…

入出力例

翻译中…

木が以下のような形状のとき、

翻译中…

image

翻译中…

以下のような入出力が考えられる。

翻译中…
プログラムへの入力 プログラムの出力
5
? 1 2
5
? 2 4
1
? 4 5
2
? 2 3
9
? 1 5
8
! 14
翻译中…

これは入出力の一つの例であり、意味のある質問をしているとは限らない。

翻译中…
题目信息
题号
abc019_4
时间限制
2 s
内存限制
256 MB

题面与样例版权归 AtCoder 及出题人所有;中文翻译由 AI 生成(CI 管线),如有出入请以原文为准。