0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Python] DFS ABC199D

Last updated at Posted at 2021-04-27

ABC199D

$3^N$ 通りの塗り方を全部探索する方法では実行時間制限に間に合わせるのは困難です。
ある頂点iの色を決めた時、iと辺で繋がっている頂点の色の探索候補は2通りしかないから、グラフが連結なら$3×2^{N-1}$通りの塗り方だけ探索すればよい。
今回グラフは連結とは限りませんが、連結成分ごとの塗り方の数の積が全体の塗り方の数となるので連結成分ごとに処理すればグラフが連結な場合に帰着することができます。

サンプルコード
import copy
n,m=map(int,input().split())
G=[[] for _ in range(n)]
# 隣接グラフ設定
for i  in range(m):
    a,b=map(int,input().split())
    a,b=a-1,b-1
    G[a].append(b)
    G[b].append(a)

done=[False]*n   # 頂点のグラフ作成済みフラグ

# 再帰で連結グラフ作成
def make_union(p,ret):
    done[p]=True
    ret.append(p)
    for q in G[p]:
        if done[q]: continue
        make_union(q,ret)
    return ret

"""
連結グラフの頂点iから再帰DFSで色を塗り、塗り方が何通りか返す
stateは色塗状況、lstは連結グラフ
"""
def dfs(i,state,lst):
    ret=0
    # 終端処理
    if i+1==len(lst):
        for c in range(3):
            for q in G[lst[i]]:
                if state[q]==c: break
            else: ret+=1
        return ret
    for c in range(3):
        state[lst[i]]=c
        for q in G[lst[i]]:
            if state[q]==c: break
        else:
            ret+=dfs(i+1,copy.copy(state),lst)
    return ret

ans=1
for p in range(n):
    if done[p]: continue # 数え済みならパス
    lst=make_union(p,[])
    ans*=dfs(0,[-1]*n,lst)
print(ans)
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?