let menu = ["Home", "Algorithms", "CodeHub", "VNOI Statistics"];
Bài này ta cần đếm số chu trình cơ bản của đồ thị đã cho. Công thức là M-N+1
cho
mỗi thành phần liên thông. Ngoài ra ta có thể DFS để đếm số cạnh nối ngược lên trên
trong quá trình DFS.
Code dsu.cpp
sử dụng disjoin set để kết hợp việc tìm các TPLT với đếm số cạnh và đỉnh
trong TPLT. Rồi dùng công thức M-N+1
để tính kết quả.
Code dfs.cpp
dùng DFS như đã nói ở trên.
#include <vector>
#include <iostream>
#include <cstdlib>
using namespace std;
struct dsu {
vector<int> cha, rank, n, m;
dsu(int N): cha(N+1), n(N+1), m(N+1) {
for (int i=1; i<=N; i++) {
cha[i] = i;
m[i] = 0;
n[i] = 1;
}
}
int find(int u) {
if (cha[u] != u) cha[u] = find(cha[u]);
return cha[u];
}
void join(int u, int v) {
u = find(u), v = find(v);
if (u == v) {
m[u]++;
return;
}
if (rand()&1) swap(u, v);
cha[v] = u;
n[u] += n[v];
m[u] += m[v] + 1;
}
};
int main() {
ios::sync_with_stdio(false); cin.tie(0);
int n, m; cin >> n >> m;
dsu d(n);
while (m--) {
int u, v; cin >> u >> v;
d.join(u, v);
}
int res = 0;
for (int i=1; i<=n; i++) if (d.cha[i] == i) res += d.m[i] - d.n[i] + 1;
cout << res;
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
typedef vector<vector<int>> dsk;
bool visited[2001], instack[2001];
int dfs(int u, int cha, dsk &ke) {
visited[u] = true;
instack[u] = true;
int res = 0;
for (int v: ke[u]) if (v != cha) {
if (instack[v]) res++;
if (!visited[v]) res += dfs(v, u, ke);
}
instack[u] = false;
return res;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
int n, m; cin >> n >> m;
dsk ke(n+1);
while (m--) {
int u, v; cin >> u >> v;
ke[u].push_back(v);
ke[v].push_back(u);
}
int res = 0;
for (int u=1; u<=n; u++) if (!visited[u]) res += dfs(u, 0, ke);
cout << res;
return 0;
}