AtCoder

ABC350 D問題(New Friends)を解く

AtCoder_ABC350_D

AtCoder が提供しているABC(AtCoder Beginner Contest)350 のD問題をC++とPythonで解いてみました。ABC350は、2024年4月20日21:00に実施されました。

AtCoder の紹介はこちらに、プログラミングの方針はこちらに記事があります。

D問題 New Friends(Difficulty : 773)

問題はリンク先をご覧ください。

ABC350 D問題 New Friends

グラフとして連結している頂点と辺の個数を求めます。AtCoder Problems による Difficulty は 773 でした。

解答案

$N$ 人のユーザを頂点、友達関係を辺とするグラフを考えます。連結しているグラフに含まれている頂点と辺の数が分かれば、それぞれの連結成分毎に

頂点の個数から2つ選ぶ組み合わせの数 - 辺の個数

の総和が求める解となります。左の項は、$_nC_2 = n \times (n \;-\;1 ) / 2$ となります。

C++ プログラム例(ABC350D)

グラフの辺を設定して(28ー33行目)、DFSで連結成分に含まれる頂点と辺の個数を求めてます。DFSのコードは定番コードとなっています。

辺は始点と終点で2回カウントしているため2で割っています(43行目)。

以下が、C++プログラムとなります。

#include <bits/stdc++.h>
using namespace std;

typedef long long int ll;

vector<vector<int>> G;
vector<bool> seen;
set<int> this_group;
ll this_group_e;

void dfs(int v)
{
	seen[v] = true;
	this_group.insert(v);
	this_group_e += G[v].size();
	for (auto next_v : G[v]) {
		if (!seen[next_v]) {
			dfs(next_v);
		}
	}
}

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

	ll result = 0;
	seen.assign(n + 1, false);
	for (int i = 1; i <= n; ++i) {
		if (!seen[i]) {
			this_group.clear();
			this_group_e = 0;
			dfs(i);
			ll s = this_group.size();
			result += s * (s - 1) / 2 - this_group_e / 2;
		}
	}

	cout << result << endl;

	return 0;
}

AC(Accepted=正しいプログラム)と判定されました。

Python プログラム例(ABC350D)

Python 版も基本的な考え方は同じです。再帰関数の呼び出し回数を増やしています(2、5行目)。以下となります。

"""AtCoder Beginner Contest 350 D"""
import sys

LIMIT = 10**6
sys.setrecursionlimit(LIMIT)


def dfs(v):
    global G, seen, this_group, this_group_e

    seen[v] = True
    this_group.add(v)
    this_group_e += len(G[v])
    for next_v in G[v]:
        if not seen[next_v]:
            dfs(next_v)


n, m = map(int, input().split())
G = [[] for i in range(n + 1)]
seen = [False] * (n + 1)
for i in range(m):
    a, b = map(int, input().split())
    G[a].append(b)
    G[b].append(a)

result = 0
for i in range(1, n + 1):
    if not seen[i]:
        this_group = set()
        this_group_e = 0
        dfs(i)
        s = len(this_group)
        result += s * (s - 1) // 2 - this_group_e // 2

print(result)

こちらも「AC」と判定されました。

最後に

ABC269からブログで記事していますが、当初はグラフの問題はほとんど解けませんでした。いまは典型的な問題であれば解けるようになりました。

引き続き ABC の問題を紹介していきます。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA