公式

C - Don’t be cycle 解説 by en_translator


Although the problem asks to find the minimum number of edges required to remove, we consider maximum number of edges that can be retained instead. If at most \(L\) edges can be retained, the answer to the original problem is \(M-L\).

Here, let \(S\) be the number of connected components in the graph. How many edges in each connected component can be retained? If a connected component has \(X\) vertices, at least \((X - 1)\) edges can be retained by taking an appropriate spanning tree. On the other hand, \(X\) or more edges can never be retained because, if you want to add \(X\) edges to a graph without any edges, the number of connected components should be reduced at least \(X\) times.

Thus, \(L = \displaystyle \sum_{i=1}^{S}(X_i-1)\), where \(X_1,X_2, \ldots\), and \(X_N\) are the sizes of the connected components. Since \(N = \displaystyle \sum_{i=1}^{S} X_i\), we have \(L = N - S\).

Therefore, the answer to he original problem is found to be \(M - N + S\). The number of connected components can be counted with DFS (Depth-First Search), BFS (Breadth-First Search), or DSU (Disjoint Set Union).

Sample code (usnig BFS)

#include <iostream>
#include <queue>
using namespace std;

int main() {
	int n, m;
	cin >> n >> m;
	vector<vector<int>> graph(n, vector<int>());
	for (int i = 0; i < m; i++) {
		int u, v;
		cin >> u >> v;
		u--; v--;
		graph[u].push_back(v);
		graph[v].push_back(u);
	}
	vector<bool> used(n);
	int s = 0;
	for (int i = 0; i < n; i++) {
		if (!used[i]) {
			s++;
			queue<int> que;
			que.push(i);
			while (!que.empty()) {
				int q = que.front(); que.pop();
				for (int v : graph[q]) {
					if (!used[v]) {
						used[v] = true;
						que.push(v);
					}
				}
			}
		}
	}
	cout << m - n + s << '\n';
}

Sample code (using ACL (AtCoder Library) that requires small amount of coding):

#include <iostream>
#include <atcoder/all>
using namespace std;
using namespace atcoder;

int main() {
	int n, m;
	cin >> n >> m;
	dsu d(n);
	int ans = 0;
	for (int i = 0; i < m; i++) {
		int u, v;
		cin >> u >> v;
		u--; v--;
		if (d.same(u, v)) ans++;
		d.merge(u, v);
	}
	cout << ans << '\n';
}

投稿日時:
最終更新: