難易度評価

難易度を1〜10段階で評価できます。投票はあとから変更・取り消しできます。

難易度(投票) Lv.3.0 (1票)

投票の分布
  1. Lv.10票
  2. Lv.20票
  3. Lv.31票
  4. Lv.40票
  5. Lv.50票
  6. Lv.60票
  7. Lv.70票
  8. Lv.80票
  9. Lv.90票
  10. Lv.100票

難易度の目安を見る ↗

ログインして難易度を投票

外部サイトへ移動します

リンク先の URL を確認してから開いてください。

別タブで開く

Odd and Even Walk

作成者 webp

難易度(作成者設定) Lv.3

難易度(投票) Lv.3.0 (1票)

解法のヒントになることがあります。
実行時間制限
2 秒
メモリ制限
512 MiB

解説

整数組 (u,v) (1≤u<v≤N)(u,v) \ (1 \le u < v \le N) を考えます。

頂点 uu と頂点 vv が異なる連結成分に属する場合、頂点 uu から頂点 vv へのウォークは存在しないため、整数組 (u,v)(u,v) は条件を満たしません。

頂点 uu と頂点 vv が同一の連結成分に属する場合を考えます。

  • その連結成分が二部グラフである場合、頂点 uu から頂点 vv へのウォークの長さの偶奇が一意に定まるため、整数組 (u,v)(u,v) は条件を満たしません。
  • その連結成分が二部グラフでない場合、整数組 (u,v)(u,v) は条件を満たします。

以上より、求める答えは、二部グラフでない連結成分について、それぞれの頂点数を nn としたときの (n2)\binom{n}{2} の総和です。

BFS や DFS を用いて二部グラフの判定と頂点数の計算を行うことで、計算量 O(N+M)O(N+M) でこの問題を解くことができます。

実装例 (C++)
#include <bits/stdc++.h>
using namespace std;

int main() {
  int n, m;
  cin >> n >> m;
  vector<vector<int>> to(n);
  for (int i = 0; i < m; i++) {
    int a, b;
    cin >> a >> b;
    a--; b--;
    to[a].push_back(b);
    to[b].push_back(a);
  }

  long long ans = 0;
  vector<int> c(n, -1);
  for (int i = 0; i < n; i++) if (c[i] == -1) {
    bool ok = true;
    int cnt = 0;
    c[i] = 0;
    queue<int> q;
    q.push(i);
    while (!q.empty()) {
      int v = q.front(); q.pop();
      cnt++;
      for (int u : to[v]) {
        if (c[u] != -1) {
          if (c[u] == c[v]) ok = false;
          continue;
        }
        c[u] = c[v] ^ 1;
        q.push(u);
      }
    }
    if (!ok) ans += (long long)cnt*(cnt-1)/2;
  }
  
  cout << ans << '\n';
  return 0;
}
実装例 (Python)
from collections import deque

n, m = map(int, input().split())
to = [[] for _ in range(n)]
for i in range(m):
  a, b = map(int, input().split())
  a, b = a-1, b-1
  to[a].append(b)
  to[b].append(a)

ans = 0
c = [-1] * n
for i in range(n):
  if c[i] != -1: continue
  ok = True
  cnt = 0
  c[i] = 0
  q = deque([i])
  while q:
    v = q.popleft()
    cnt += 1
    for u in to[v]:
      if c[u] != -1:
        if c[u] == c[v]: ok = False
        continue
      c[u] = c[v] ^ 1
      q.append(u)
  if not ok: ans += cnt*(cnt-1)//2

print(ans)

ユーザー解説

ユーザー解説を書く

ユーザー解説はまだありません。