Luogu P1726 上白泽慧音

解题思路

这一眼看上去就知道要求最大连通分量。用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\n", ans[0]);
    for(int i=1; i<=ans[0]; i++) printf("%d ", ans[i]);
    return 0;
}

 

posted @ 2018-08-07 20:19  Mystical-W  阅读(155)  评论(0编辑  收藏  举报