【tarjan强连通分量】洛谷P1726 上白泽慧音
题目传送门
妥妥的强连通模板啊(详细解释戳这里)
#include <bits/stdc++.h>
#define MAXN 5005
#define MAXM 50005*2
using namespace std;
int n, m, cnt;
int head[MAXN], Next[MAXM], vet[MAXM];
vector<int> ans;
//链式前向星存边
void add(int x, int y){
cnt++;
Next[cnt] = head[x];
vet[cnt] = y;
head[x] = cnt;
}
int T, dfn[MAXN], low[MAXN]; //时间戳,子树中连通的最小dfn
bool vis[MAXN]; //判断点是否在栈内
stack<int> s;
void tarjan(int x){
T++;
dfn[x] = low[x] = T;
s.push(x);
vis[x] = true;
for (int i = head[x]; i; i = Next[i]) {
int v = vet[i];
if(!dfn[v]){ //没有访问过,为搜索树的一条边,需要继续搜索
tarjan(v);
low[x] = min(low[x], low[v]); //回溯赋值
}
else if(vis[v]){ //v在栈中,即为返祖边或者横叉边
low[x] = min(low[x], dfn[v]);
}
}
if(dfn[x] == low[x]){ //是一个强连通分量的搜索树根
int t = -1;
vector<int> vec;
vec.clear();
while(t != x){ //出栈直到x
t = s.top();
vec.push_back(t);
s.pop();
vis[t] = false;
}
if(vec.size() > ans.size()){ //记录答案
ans = vec;
}
}
}
int main()
{
cin >> n >> m;
int a,b,t;
for (int i = 1; i <= m; ++i) {
scanf("%d %d %d", &a, &b, &t);
if(a == b)
continue;
add(a,b);
if(t == 2){
add(b,a);
}
}
for (int i = 1; i <= n; ++i) { //搜索强连通分量
if(!dfn[i])
tarjan(i);
}
cout << ans.size() << endl;
sort(ans.begin(), ans.end());
for (int i = 0; i < ans.size(); ++i) {
cout << ans[i] << " ";
}
cout << endl;
return 0;
}