Thành phần liên thông mạnh
Mở code
#include <bits/stdc++.h>
using namespace std;
int soDinh, soCanh;
vector<int> dsKe[10005];
int dfn[10005], low[10005], boDemThoiGian;
int nganXep[10005], dinhNganXep;
bool dangTrongXep[10005];
int soThanhPhan, thuocThanhPhan[10005];
vector<int> thanhPhan[10005];
bool daXuat[10005];
void tarjan(int dinh) {
dfn[dinh] = low[dinh] = ++boDemThoiGian;
nganXep[++dinhNganXep] = dinh;
dangTrongXep[dinh] = true;
for (auto ke : dsKe[dinh]) {
if (!dfn[ke]) {
tarjan(ke);
low[dinh] = min(low[dinh], low[ke]);
} else if (dangTrongXep[ke]) {
low[dinh] = min(low[dinh], dfn[ke]);
}
}
if (low[dinh] == dfn[dinh]) {
soThanhPhan++;
int temp;
do {
temp = nganXep[dinhNganXep--];
dangTrongXep[temp] = false;
thuocThanhPhan[temp] = soThanhPhan;
thanhPhan[soThanhPhan].push_back(temp);
} while (temp != dinh);
}
}
int main() {
cin >> soDinh >> soCanh;
for (int i = 0; i < soCanh; i++) {
int u, v;
cin >> u >> v;
dsKe[u].push_back(v);
}
for (int i = 1; i <= soDinh; i++)
if (!dfn[i]) tarjan(i);
cout << soThanhPhan << endl;
for (int i = 1; i <= soDinh; i++) {
if (daXuat[thuocThanhPhan[i]]) continue;
daXuat[thuocThanhPhan[i]] = true;
sort(thanhPhan[thuocThanhPhan[i]].begin(), thanhPhan[thuocThanhPhan[i]].end());
for (auto x : thanhPhan[thuocThanhPhan[i]])
cout << x << " ";
cout << endl;
}
return 0;
}
Rút gọn đồ thị
Mở code
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int soDinh, soCanh;
ll trongSo[10005];
struct Canh {
int u, v;
} dsCanh[100005];
vector<int> dsKe[10005];
vector<int> dsRutGon[10005];
ll trongSoRutGon[10005];
int dfn[10005], low[10005], boDemThoiGian;
int nganXep[10005], dinhNganXep;
bool dangTrongXep[10005];
int thuocThanhPhan[10005];
int soThanhPhan;
ll tongTrongSo[10005];
void dfs(int dinh) {
dfn[dinh] = low[dinh] = ++boDemThoiGian;
nganXep[++dinhNganXep] = dinh;
dangTrongXep[dinh] = true;
for (auto ke : dsKe[dinh]) {
if (!dfn[ke]) {
dfs(ke);
low[dinh] = min(low[dinh], low[ke]);
} else if (dangTrongXep[ke]) {
low[dinh] = min(low[dinh], dfn[ke]);
}
}
if (low[dinh] == dfn[dinh]) {
soThanhPhan++;
int temp;
do {
temp = nganXep[dinhNganXep--];
dangTrongXep[temp] = false;
tongTrongSo[soThanhPhan] += trongSo[temp];
thuocThanhPhan[temp] = soThanhPhan;
} while (temp != dinh);
}
}
int bacVao[10005];
ll ketQua[10005];
int main() {
cin >> soDinh >> soCanh;
for (int i = 1; i <= soDinh; i++)
cin >> trongSo[i];
for (int i = 0; i < soCanh; i++) {
int u, v;
cin >> u >> v;
dsCanh[i] = {u, v};
dsKe[u].push_back(v);
}
for (int i = 1; i <= soDinh; i++)
if (!dfn[i]) dfs(i);
for (int i = 0; i < soCanh; i++) {
if (thuocThanhPhan[dsCanh[i].u] != thuocThanhPhan[dsCanh[i].v]) {
int u = thuocThanhPhan[dsCanh[i].u];
int v = thuocThanhPhan[dsCanh[i].v];
dsRutGon[u].push_back(v);
bacVao[v]++;
}
}
for (int i = 1; i <= soThanhPhan; i++)
trongSoRutGon[i] = tongTrongSo[i];
queue<int> hangDoi;
for (int i = 1; i <= soThanhPhan; i++)
if (bacVao[i] == 0) {
ketQua[i] = trongSoRutGon[i];
hangDoi.push(i);
}
while (!hangDoi.empty()) {
int u = hangDoi.front(); hangDoi.pop();
for (auto v : dsRutGon[u]) {
ketQua[v] = max(ketQua[v], ketQua[u] + trongSoRutGon[v]);
bacVao[v]--;
if (bacVao[v] == 0) hangDoi.push(v);
}
}
ll maxKetQua = 0;
for (int i = 1; i <= soThanhPhan; i++)
maxKetQua = max(maxKetQua, ketQua[i]);
cout << maxKetQua;
return 0;
}
Điểm khớp
Mở code
#include <bits/stdc++.h>
using namespace std;
int soDinh, soCanh;
vector<int> dsKe[20005];
int dfn[20005], low[20005], boDemThoiGian;
int soDiemKhop, laDiemKhop[20005];
void tarjan(int dinh, int goc) {
dfn[dinh] = low[dinh] = ++boDemThoiGian;
int conTre = 0;
for (auto ke : dsKe[dinh]) {
if (!dfn[ke]) {
conTre++;
tarjan(ke, goc);
low[dinh] = min(low[dinh], low[ke]);
if (low[ke] >= dfn[dinh] && dinh != goc)
if (!laDiemKhop[dinh]) {
soDiemKhop++;
laDiemKhop[dinh] = 1;
}
} else {
low[dinh] = min(low[dinh], dfn[ke]);
}
}
if (dinh == goc && conTre >= 2)
if (!laDiemKhop[dinh]) {
soDiemKhop++;
laDiemKhop[dinh] = 1;
}
}
int main() {
cin >> soDinh >> soCanh;
for (int i = 0; i < soCanh; i++) {
int u, v;
cin >> u >> v;
dsKe[u].push_back(v);
dsKe[v].push_back(u);
}
for (int i = 1; i <= soDinh; i++)
if (!dfn[i]) tarjan(i, i);
cout << soDiemKhop << endl;
for (int i = 1; i <= soDinh; i++)
if (laDiemKhop[i]) cout << i << " ";
return 0;
}
Thành phần liên thông chập (đỉnh)
Mở code
#include <bits/stdc++.h>
using namespace std;
int soDinh, soCanh;
vector<int> dsKe[500005];
int dfn[500005], low[500005], boDemThoiGian;
int nganXep[500005], dinhNganXep;
int soThanhPhan;
vector<int> thanhPhan[500005];
void tarjan(int dinh, int goc) {
dfn[dinh] = low[dinh] = ++boDemThoiGian;
nganXep[++dinhNganXep] = dinh;
int conTre = 0;
for (auto ke : dsKe[dinh]) {
if (!dfn[ke]) {
conTre++;
tarjan(ke, goc);
low[dinh] = min(low[dinh], low[ke]);
if (low[ke] >= dfn[dinh]) {
soThanhPhan++;
int temp;
do {
temp = nganXep[dinhNganXep--];
thanhPhan[soThanhPhan].push_back(temp);
} while (temp != ke);
thanhPhan[soThanhPhan].push_back(dinh);
}
} else {
low[dinh] = min(low[dinh], dfn[ke]);
}
}
if (dinh == goc && conTre == 0)
thanhPhan[++soThanhPhan].push_back(dinh);
}
int main() {
cin >> soDinh >> soCanh;
for (int i = 0; i < soCanh; i++) {
int u, v;
cin >> u >> v;
dsKe[u].push_back(v);
dsKe[v].push_back(u);
}
for (int i = 1; i <= soDinh; i++)
if (!dfn[i]) {
dinhNganXep = 0;
tarjan(i, i);
}
cout << soThanhPhan << endl;
for (int i = 1; i <= soThanhPhan; i++) {
cout << thanhPhan[i].size() << " ";
for (auto x : thanhPhan[i]) cout << x << " ";
cout << endl;
}
return 0;
}
Thành phần liên thông chập (cạnh)
Mở code
#include <bits/stdc++.h>
using namespace std;
int soDinh, soCanh, soCanhHuong;
vector<pair<int, int>> dsKe[500005];
int dfn[500005], low[500005], boDemThoiGian;
int soThanhPhan;
vector<int> thanhPhan[500005];
int nganXep[500005], dinhNganXep;
void tarjan(int dinh, int canh) {
dfn[dinh] = low[dinh] = ++boDemThoiGian;
nganXep[++dinhNganXep] = dinh;
for (auto ke : dsKe[dinh]) {
if (!dfn[ke.first]) {
tarjan(ke.first, ke.second);
low[dinh] = min(low[dinh], low[ke.first]);
} else if (ke.second != (canh ^ 1)) {
low[dinh] = min(low[dinh], dfn[ke.first]);
}
}
if (low[dinh] == dfn[dinh]) {
soThanhPhan++;
int temp;
do {
temp = nganXep[dinhNganXep--];
thanhPhan[soThanhPhan].push_back(temp);
} while (temp != dinh);
}
}
int main() {
cin >> soDinh >> soCanh;
for (int i = 0; i < soCanh; i++) {
int u, v;
cin >> u >> v;
dsKe[u].push_back({v, soCanhHuong++});
dsKe[v].push_back({u, soCanhHuong++});
}
for (int i = 1; i <= soDinh; i++)
if (!dfn[i]) {
dinhNganXep = 0;
tarjan(i, -1);
}
cout << soThanhPhan << endl;
for (int i = 1; i <= soThanhPhan; i++) {
cout << thanhPhan[i].size() << " ";
for (auto x : thanhPhan[i]) cout << x << " ";
cout << endl;
}
return 0;
}
Không sử dụng ngăn xếp cho: điểm khớp, thành phần liên thông chập (đỉnh)