目录
强连通分量
// problem :
#include <bits/stdc++.h>
using namespace std;
#define ll long long
typedef pair<int, int> PII;
#define pb push_back
const int N = 100005;
int n, m;
vector<int>e[N]; // 存图
stack<int>stk; // 存放点
int dfn[N], idx, low[N]; // dfn[u] : u点是dfn[u]个访问到的; idx : 访问的顺序 low[u] : u点能跳到的最高的点
bool ins[N]; // ins[u] : u点是否在栈里
int cnt, bel[N]; // cnt : 强连通分量的个数 bel[u] : u点属于第bel[u]个强连通分量
vector<vector<int>> scc;
void dfs(int u) {
dfn[u] = low[u] = ++idx;
stk.push(u);
ins[u] = true;
for (auto v : e[u]) {
if (!dfn[v]) {
dfs(v);
}
if (ins[v]) low[u] = min(low[u], low[v]);
}
if (dfn[u] == low[u]) {
cnt++;
vector<int> c;
while (true) {
int v = stk.top(); stk.pop();
c.push_back(v);
ins[v] = false;
bel[v] = cnt;
if (v == u) break;
}
sort(c.begin(), c.end());
scc.push_back(c);
}
}
int main(){
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; ++i) {
int u, v; scanf("%d%d", &u, &v);
e[u].push_back(v);
}
for (int i = 1; i <= n; ++i) {
if (!dfn[i])
dfs(i);
}
sort(scc.begin(), scc.end());
for (auto c : scc) {
for (auto u : c) {
printf("%d ", u);
}
puts("");
}
return 0;
}
最受欢迎的牛
每头牛相当于一个点。问题转换为:有多少个点,所有的点都可达。
这里引入DAG(有向无环图):
唯一汇点
解题: 先缩点,将每一个强连通分量缩成一个点。统一每一个“点”的出度是否为0,如果有多个出度为0的点,显然答案为0,否则就输出这个点的大小(这个强连通分量内有多少个点)
// problem :
#include <bits/stdc++.h>
using namespace std;
#define ll long long
typedef pair<int, int> PII;
#define pb push_back
const int N = 100005;
int n, m;
vector<int>e[N];
stack<int>stk;
int dfn[N], idx, low[N];
bool ins[N];
int cnt, bel[N];
int sz[N]; // sz[u] : 编号为u的强连通分量的点的个数
int outd[N]; // outd[u] : 编号为u的强连通分量的缩点后的出度
void dfs(int u) {
dfn[u] = low[u] = ++idx;
stk.push(u);
ins[u] = true;
for (auto v : e[u]) {
if (!dfn[v]) {
dfs(v);
}
if (ins[v]) low[u] = min(low[u], low[v]);
}
if (dfn[u] == low[u]) {
cnt++;
while (true) {
int v = stk.top(); stk.pop();
ins[v] = false;
sz[cnt]++;
bel[v] = cnt;
if (v == u) break;
}
}
}
int main(){
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; ++i) {
int u, v; scanf("%d%d", &u, &v);
e[u].push_back(v);
}
for (int i = 1; i <= n; ++i) {
if (!dfn[i])
dfs(i);
}
for (int u = 1; u <= n; ++u) {
for (auto v : e[u]) {
if (bel[u] != bel[v]) {
outd[bel[u]]++;
}
}
}
int cnts = 0, cntv = 0;
for (int i = 1; i <= cnt; ++i) {
if (outd[i] == 0) {
cnts++;
cntv += sz[i];
}
}
if (cnts >= 2) puts("0");
else printf("%d\n", cntv);
return 0;
}