解题思路
这一眼看上去就知道要求最大连通分量。用Tarjan算法进行求解,关键就是怎么按照字典序输出。从Tarjan的搜索顺序来看,搜出来的东西就是按照字典序来的。越往后面的字典序越大。
所以我们直接将最后一次更新时的连通分量输出就行了
附上代码
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <stack> #include <cassert> using namespace std; stack <int> S; const int maxn = 1e5+3; int n, m, fir[maxn], nx[maxn], u[maxn], v[maxn], s, cnt, uu, vv, tot; int dfn[maxn], low[maxn], Index, ans[maxn], Ans[maxn]; bool vis[maxn]; inline void addedge(int fr, int to) { u[++cnt] = fr; v[cnt] = to; nx[cnt] = fir[fr]; fir[fr] = cnt; } inline void Tarjan(int x) { dfn[x] = low[x] = ++ Index; vis[x] = 1; S.push(x); int k = fir[x]; while (k != -1) { if(!dfn[v[k]]) { Tarjan(v[k]); low[x] = min(low[x], low[v[k]]); } else if(vis[v[k]]) low[x] = min(low[x], dfn[v[k]]); k = nx[k]; } if(low[x] == dfn[x]) { int tot = 0; while (!S.empty()) { k = S.top(); vis[k] = 0; S.pop(); Ans[++tot] = k; if(x == k) break; } if(tot >= ans[0]) { for(int i=1; i<=tot; i++) { ans[i] = Ans[i]; } ans[0] = tot; } } } int main() { scanf("%d%d", &n, &m); memset(fir, -1, sizeof(fir)); for(int i=1; i<=m; i++) { scanf("%d%d%d", &uu, &vv, &s); if(s == 1) addedge(uu, vv); else addedge(uu, vv), addedge(vv, uu); } for(int i=1; i<=n; i++) { if(!dfn[i]) Tarjan(i); } sort(ans+1, ans+1+ans[0]); printf("%d ", ans[0]); for(int i=1; i<=ans[0]; i++) printf("%d ", ans[i]); return 0; }