Codeforces Round #306 Div2 D: Regular Bridge
解法
k=1の時はサンプルをコピペする。
橋を取り除いた時、残ったグラフの片方は次数がk-1の頂点が1つ存在し、残りの頂点の次数はkである。この部分グラフの頂点の数をnとすると、辺の数は((n-1)*k+k-1)/2=(n*k-1)/2となる。これは整数でなければならないので、kが偶数の時は条件を満たすグラフは存在しない。
kが奇数の時、(n*k-1)/2が整数になるため、nも奇数であることが分かる。各頂点の次数はkまたはk-1なのでn>kでなければならないため、ひとまずn=k+2とする。
k+2角形(n角形)をつくり、対角線を引くと、全ての頂点の次数がk+1になるので、そこから、頂点1と頂点2を結ぶ辺、頂点3と頂点4を結ぶ辺、頂点5と頂点6を結ぶ辺、...、頂点k-2と頂点k-1を結ぶ辺、を取り除くと、頂点k、頂点k+1、頂点k+2の3つの頂点の次数がk+1、残りの頂点の次数がkになる。そこから頂点kと頂点k+2を結ぶ辺、頂点k+1と頂点k+2を結ぶ辺を取り除くと、頂点k+2の次数だけk-1、残りの次数がkになる。
この部分グラフを2つ作り、次数がk-1の頂点同士を結ぶと、条件を満たすグラフが完成する。
コード
import java.util.Scanner; import java.util.TreeSet; public class Main { private final int INF = 10000000; public void solve() { Scanner sc = new Scanner(System.in); int k = sc.nextInt(); sc.close(); if (k % 2 == 0) { System.out.println("NO"); return; } if (k == 1) { System.out.println("YES"); System.out.println("2 1"); System.out.println("1 2"); return; } System.out.println("YES"); System.out.println(((k + 2) * 2) + " " + (k * k + 2 * k)); TreeSet<Integer> set = new TreeSet<Integer>(); for (int i = 1; i <= k + 1; i++) { for (int j = i + 1; j <= k + 2; j++) { set.add(i * INF + j); set.add((i + k + 2) * INF + (j + k + 2)); } } for (int i = 1; i * 2 < k; i++) { set.remove((i * 2 - 1) * INF + (i * 2)); set.remove((i * 2 - 1 + k + 2) * INF + (i * 2 + k + 2)); } set.remove(k * INF + (k + 2)); set.remove((k + 1) * INF + (k + 2)); set.remove((2 * k + 2) * INF + (2 * k + 4)); set.remove((2 * k + 3) * INF + (2 * k + 4)); for (Integer integer : set) { int a = integer / INF; int b = integer % INF; System.out.println(a + " " + b); } System.out.println((k + 2) + " " + (2 * k + 4)); } public static void main(String[] args) { new Main().solve(); } }