D - Make 2-Regular Graph 解説
by
sounansya
すべての頂点の次数が \(2\) である単純無向グラフと入力で与えられる \(G\) の辺の共通部分の個数の最大値を \(K\) とすると、求める答えは \(N+M-2K\) となります。したがって、この \(K\) の値を求めることを考えます。
ある頂点集合を決め打った時、その頂点集合からなるサイクルと \(G\) の辺の共通部分の個数の最大値を bitDP で求めることを考えます。サイクルは番号が最も小さい頂点 \(k\) を一つ決め打ち、そこから \(N+1-k\) 頂点のみを考えることで bitDP ができます。
最終的な答えは \(S_1 \cup S_2 \cup \ldots \cup S_c = \lbrace 1,2,\ldots,N\rbrace\) を満たす互いに素な集合 \(S_1,S_2,\ldots,S_c\) 全てに対する \(d[S_1]+d[S_2]+\ldots+d[S_c]\) の最小値(ただし \(d[S]\) は上の bitDP を考えた際のサイクル \(S\) と \(G\) の辺の共通部分の個数の最大値)となります。
詳しくは実装例を参考にしてください。
計算量は \(O(N^22^N+3^N)=O(3^N)\) です。
n, m = map(int, input().split())
g = [[False] * n for _ in range(n)]
for _ in range(m):
a, b = map(int, input().split())
a, b = a - 1, b - 1
g[a][b] = True
g[b][a] = True
INF = 100
dp = [-INF] * (1 << n)
dp[0] = 0
for st in range(n - 2):
nn = n - st
d = [[-INF] * (1 << (nn - 1)) for _ in range(nn)]
d[0][0] = 0
for s in range(1 << (nn - 1)):
for i in range(nn):
if d[i][s] == -INF:
continue
for j in range(1, nn):
ss = s | (1 << (j - 1))
if ss == s:
continue
d[j][ss] = max(d[j][ss], d[i][s] + g[i + st][j + st])
if i == 0 or s == (1 << (i - 1)):
continue
ss = ((s << 1) | 1) << st
dp[ss] = max(dp[ss], d[i][s] + g[i + st][st])
for s in range(1 << n):
t = s
while t:
dp[s] = max(dp[s], dp[t] + dp[t ^ s])
t = (t - 1) & s
print(n + m - 2 * dp[-1])
投稿日時:
最終更新: