Problem:
Evacuation Site
The council of your home city decided to build a public evacuation site to prepare for natural disasters.
The evacuation site is desired to be built at a location reachable from as many locations across the city
as possible, even when many road segments are closed due to a natural disaster.
Given the road network of the city, please find the best candidate locations.
The road network is specified as an undirected graph.
The nodes of the graph correspond to various locations in the city area,
and the edges are two-way road segments connecting the locations.
Each road segment is assigned a positive integer representing the
assumed strength
against disasters.
A road segment with assumed strength
s
is expected to be available
on a disaster of level below
s
, but will be closed
on a disaster of level above or equal to
s
.
Adequacy of a location as an evacuation site is assessed by the following ordering.
Let us define
r
s
(
v
) as
the number of locations that is directly or indirectly connected to the location
v
via road segments available even on the level-
s
disaster.
We define the location
u
is more suitable than the location
v
as an evacuation site
if and only if there exists some
k
≥ 1 satisfying
r
1
(
u
) =
r
1
(
v
),
r
2
(
u
) =
r
2
(
v
),
...
r
k
-1
(
u
) =
r
k
-1
(
v
), and
r
k
(
u
) >
r
k
(
v
).
Please find the best locations based on the above criterion.
If two or more locations are rated equally as the best, enumerate all of them.
Input
The input consists of multiple datasets, each in the following format.
n
m
a
1
b
1
s
1
...
a
m
b
m
s
m
n
is a positive integer less than or equal to 10
5
,
representing the number of locations.
m
is a non-negative integer less than or equal to 10
5
,
representing the number of road segments.
The locations in the city are given ID numbers 1 through
n
.
The
i
-th segment connects the locations
a
i
and
b
i
,
and its assumed strength is
s
i
.
Each of
a
i
,
b
i
, and
s
i
is an integer
and they satisfy
1 ≤
a
i
<
b
i
≤
n
and
1 ≤
s
i
≤ 10
5
.
When
i
≠
j
, either
a
i
≠
a
j
or
b
i
≠
b
j
holds.
The given graph is connected.
That is, there is at least one path between every pair of locations.
The end of the input is indicated by a line containing two zeros. The number of datasets does not exceed 50.
Output
For each dataset, output the list of the ID numbers of all of the locations
most suitable with the criterion described above
separated by a space character, in the increasing order, in a line.
Sample Input
3 3
1 2 1
1 3 2
2 3 3
3 3
1 2 3
1 3 3
2 3 3
5 5
1 2 5
2 3 1
3 4 2
3 5 1
4 5 2
0 0
Output for the Sample Input
2 3
1 2 3
3 4 5

Submitted solutions:

code_snippet: #line 1 "library/Template/template.hpp"
#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T, typename S = T> S SUM(const vector<T> &a) {
    return accumulate(ALL(a), S(0));
}
template <typename S, typename T = S> S POW(S a, T b) {
    S ret = 1, base = a;
    for (;;) {
        if (b & 1)
            ret *= base;
        b >>= 1;
        if (b == 0)
            break;
        base *= base;
    }
    return ret;
}
template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define debug 1
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define debug 0
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}
#line 2 "library/Utility/fastio.hpp"
#include <unistd.h>
namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf

uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio

using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */
#line 2 "library/Utility/random.hpp"

namespace Random {
mt19937_64 randgen(chrono::steady_clock::now().time_since_epoch().count());
using u64 = unsigned long long;
u64 get() {
    return randgen();
}
template <typename T> T get(T L) { // [0,L]
    return get() % (L + 1);
}
template <typename T> T get(T L, T R) { // [L,R]
    return get(R - L) + L;
}
double uniform() {
    return double(get(1000000000)) / 1000000000;
}
string str(int n) {
    string ret;
    rep(i, 0, n) ret += get('a', 'z');
    return ret;
}
template <typename Iter> void shuffle(Iter first, Iter last) {
    if (first == last)
        return;
    int len = 1;
    for (auto it = first + 1; it != last; it++) {
        len++;
        int j = get(0, len - 1);
        if (j != len - 1)
            iter_swap(it, first + j);
    }
}
template <typename T> vector<T> select(int n, T L, T R) { // [L,R]
    if (n * 2 >= R - L + 1) {
        vector<T> ret(R - L + 1);
        iota(ALL(ret), L);
        shuffle(ALL(ret));
        ret.resize(n);
        return ret;
    } else {
        unordered_set<T> used;
        vector<T> ret;
        while (SZ(used) < n) {
            T x = get(L, R);
            if (!used.count(x)) {
                used.insert(x);
                ret.push_back(x);
            }
        }
        return ret;
    }
}

void relabel(int n, vector<pair<int, int>> &es) {
    shuffle(ALL(es));
    vector<int> ord(n);
    iota(ALL(ord), 0);
    shuffle(ALL(ord));
    for (auto &[u, v] : es)
        u = ord[u], v = ord[v];
}
template <bool directed, bool multi, bool self>
vector<pair<int, int>> genGraph(int n, int m) {
    vector<pair<int, int>> cand, es;
    rep(u, 0, n) rep(v, 0, n) {
        if (!self and u == v)
            continue;
        if (!directed and u > v)
            continue;
        cand.push_back({u, v});
    }
    if (m == -1)
        m = get(SZ(cand));
    // chmin(m, SZ(cand));
    vector<int> ord;
    if (multi)
        rep(_, 0, m) ord.push_back(get(SZ(cand) - 1));
    else {
        ord = select(m, 0, SZ(cand) - 1);
    }
    for (auto &i : ord)
        es.push_back(cand[i]);
    relabel(n, es);
    return es;
}
vector<pair<int, int>> genTree(int n) {
    vector<pair<int, int>> es;
    rep(i, 1, n) es.push_back({get(i - 1), i});
    relabel(n, es);
    return es;
}
}; // namespace Random

/**
 * @brief Random
 */
#line 4 "sol.cpp"

#line 2 "library/DataStructure/unionfind.hpp"

struct UnionFind{
    vector<int> par; int n;
    UnionFind(){}
    UnionFind(int _n):par(_n,-1),n(_n){}
    int root(int x){return par[x]<0?x:par[x]=root(par[x]);}
    bool same(int x,int y){return root(x)==root(y);}
    int size(int x){return -par[root(x)];}
    bool unite(int x,int y){
        x=root(x),y=root(y); if(x==y)return false;
        if(size(x)>size(y))swap(x,y);
        par[y]+=par[x]; par[x]=y; n--; return true;
    }
};

/**
 * @brief Union Find
 */
#line 6 "sol.cpp"

int main() {
    for (;;) {
        int n, m;
        read(n, m);
        if (n == 0)
            break;
        if (n == 1) {
            print(1);
            continue;
        }

        using P = pair<int, int>;
        using T = array<int, 3>;
        vector es(101010, vector<P>());
        rep(_, 0, m) {
            int x, y, w;
            read(x, y, w);
            x--, y--;
            es[w].push_back({x, y});
        }
        UnionFind uni(n);
        map<P, vector<P>> tree;
        vector<int> pre(n, 101010);
        map<P, int> sz;
        P root = {101010, 0};
        rrep(w, 1, 100001) {
            map<int, vector<int>> mp;
            for (auto &[u, v] : es[w]) {
                if (!uni.same(u, v)) {
                    if (!mp.count(uni.root(u))) {
                        mp[uni.root(u)].push_back(uni.root(u));
                    }
                    if (!mp.count(uni.root(v))) {
                        mp[uni.root(v)].push_back(uni.root(v));
                    }
                    int other = uni.root(u) ^ uni.root(v);
                    uni.unite(u, v);
                    int rt = uni.root(u);
                    other ^= rt;
                    if (SZ(mp[rt]) < SZ(mp[other])) {
                        swap(mp[rt], mp[other]);
                    }
                    for (auto &x : mp[other])
                        mp[rt].push_back(x);
                    mp.erase(other);
                }
            }
            for (auto &[rt, vs] : mp) {
                for (auto &x : vs) {
                    tree[{w, rt}].push_back({pre[x], x});
                }
                pre[rt] = w;
                root = {w, rt};
                sz[{w, rt}] = uni.size(rt);
            }
        }
        // show(tree);

        vector<int> ret;
        vector cand(101010, vector<P>());
        cand[root.first].push_back(root);
        set<pair<int, P>> st;
        st.insert({sz[root], root});
        rep(w, 1, 101010) {
            for (auto &v : cand[w]) {
                st.erase({sz[v], v});
                for (auto &to : tree[v]) {
                    st.insert({sz[to], to});
                }
            }
            if (SZ(st) == 0)
                continue;
            int mx = (*st.rbegin()).first;
            for (auto &v : cand[w])
                for (auto &to : tree[v])
                    if (mx == sz[to]) {
                        if (to.first == 101010) {
                            ret.push_back(to.second + 1);
                        } else {
                            cand[to.first].push_back(to);
                        }
                    }
            while (SZ(st) > 0) {
                if ((*st.begin()).first < mx)
                    st.erase(st.begin());
                else
                    break;
            }
        }

        sort(ALL(ret));
        print(ret);
    }
    return 0;
}
accuracy: 1
time_ms: 430
memory_kb: 38548
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define vi vector<int>
#define vl vector<ll>
#define ov4(a, b, c, d, name, ...) name
#define rep3(i, a, b, c) for(ll i = (a); i < (b); i += (c))
#define rep2(i, a, b) rep3(i, a, b, 1)
#define rep1(i, n) rep2(i, 0, n)
#define rep0(n) rep1(aaaaa, n)
#define rep(...) ov4(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__)
#define per(i, a, b) for(ll i = (a)-1; i >= (b); i--)
#define fore(e, v) for(auto&& e : v)
#define all(a) begin(a), end(a)
#define sz(a) (int)(size(a))
#define lb(v, x) (lower_bound(all(v), x) - begin(v))
#define eb emplace_back

template<typename T, typename S> bool chmin(T& a, const S& b) { return a > b ? a = b, 1 : 0; }
template<typename T, typename S> bool chmax(T& a, const S& b) { return a < b ? a = b, 1 : 0; }
 
const int INF = 1e9 + 100;
const ll INFL = 3e18 + 100;
 
#define i128 __int128_t
 
struct _ {
   _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;

void debug(auto ...vs) {
    ((cerr << vs << " "), ...) << endl;
}

struct UnionFind {
    int n;
    vi par;
    stack<pii> history;

    UnionFind(int n) : n(n), par(n, -1) {}

    int leader(int x) {
        if (par[x] < 0) return x;
        return leader(par[x]);
    }

    pii merge(int x, int y) {
        x = leader(x);
        y = leader(y);
        if (par[x] > par[y]) {
            swap(x, y);
        }
        
        history.emplace(x, par[x]);
        history.emplace(y, par[y]);
        if (x == y) {
            return {-1, -1};
        }

        par[x] += par[y];
        par[y] = x;
        return {x, y};
    }
    int size(int x) {
        return -par[leader(x)];
    }
    pii rollback() {
        auto [y, py] = history.top();history.pop();
        par[y] = py;
        auto [x, px] = history.top();history.pop();
        par[x] = px;
        
        return {x, y};
    }
};


void solve(int n, int m) {
	const int B = 1e5+10;
    vector<vector<pii>> E(B);
    rep(i, m) {
        int a, b, s;cin >> a >> b >> s;
        a--, b--;
        E[s].emplace_back(a, b);
    }
    UnionFind uf(n);
    vector<set<int>> se(B);
    per(t, B, 0) {
        for(auto [a, b] : E[t]) {
            se[t].insert(uf.leader(a));
            se[t].insert(uf.leader(b));
        }
        for(auto [a, b] : E[t]) {
            auto [x, y] = uf.merge(a, b);
        }
    }
    vi ok(n, 0);ok[uf.leader(0)] = n;
    int last = n, cnt = 1;
    rep(t, B) {
        vector<pii> sp;
        int mx = -1, c = 0;
        map<int, int> mp;
        for(auto x: se[t]) {
            if (ok[uf.leader(x)] ) {
                mp[x] = uf.leader(x);
            }
        }
        for (auto [x, y] : mp) {
            if (ok[y]) {
                ok[y] = 0;
                cnt--;
            }
        }
        rep(sz(E[t])) {
            auto [x, y] = uf.rollback();
        }
        
        for(auto [x, y] : mp) {
            chmax(mx, uf.size(x));
        }

        if (cnt) {
            mx = last;
        }
        else {
            last = mx;
        }
        
        for(auto [x, y] : mp) {
            if (uf.size(x) == mx) {
                ok[x] = 1;
                cnt++;
            }
        }
           
    }   
    vi res;
    rep(i, n) {
        if (ok[i]) res.emplace_back(i);
    }
    rep(i, sz(res)) {
        if (i) cout << " ";
        cout << res[i] + 1;
    }
    cout << endl;

}

int main() {
    // int T;cin >> T;
	// int T = 1;
    while(true) {
        int n, m;cin >>n >> m;
        if (n == 0) break;
        solve(n, m);
    }
    
}
accuracy: 1
time_ms: 150
memory_kb: 25484
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
#define rep(i,a,b) for (int i=(int)(a);i<(int)(b);i++)
#define all(p) p.begin(),p.end()

struct UF {
    int n;
    vector<int> wei, par;
    UF (int n_){
        n = n_;
        wei.resize(n, 1);
        par.resize(n);
        rep(i, 0, n) par[i] = i;
    }
    int root(int a){
        if (par[a] == a) return a;
        return par[a] = root(par[a]);
    }
    int same(int a, int b){
        a = root(a);
        b = root(b);
        return a == b;
    }
    int unite(int a, int b){
        a = root(a), b = root(b);
        if (a == b) return 0;
        if (a < b) swap(a, b);
        wei[a] += wei[b];
        par[b] = a;
        return 1;
    }
};



void solve(int N, int M){
    UF T(N);
    const int L = 100'000;
    vector<vector<pair<int, int>>> E(L);
    rep(i, 0, M){
        int a, b, c;
        cin >> a >> b >> c;
        a--, b--, c--;
        E[c].push_back({a, b});
    }
    vector<vector<pair<int, pair<int, int>>>> G(N * 2);
    vector<int> pos(N);
    vector<int> sz(N + N);
    rep(i, 0, N) pos[i] = i, sz[i] = 1;
    int root = N - 1;
    for (int s = L - 1; s >= 0; s--){
        vector<int> seen;
        for (auto [a, b] : E[s]){
            if (T.same(a, b)) continue;
            seen.push_back(T.root(a));
            seen.push_back(T.root(b));
        }
        sort(all(seen));
        seen.erase(unique(all(seen)), seen.end());
        for (auto [a, b] : E[s]){
            T.unite(a, b);
        }
        sort(all(seen), [&](int l, int r){
           return T.root(l) < T.root(r);
        });
        for (int l = 0, r = 0; l < (int)seen.size(); l = r){
            root++;
            while (r != (int)seen.size() && T.root(seen[l]) == T.root(seen[r])){
                int a = seen[r];
                sz[root] = T.wei[T.root(a)];
                G[root].push_back({pos[a], {s, sz[pos[a]]}});
                pos[a] = root;
                r++;
            }
        }
    }
    vector<int> ans = {root};
    /*rep(i, 0, root + 1){
        cout << i << " : " ;
        for (auto [a, b] : G[i]) cout << a << " ";
        cout << endl;
    }*/
    while (true){
        sort(all(ans));
        if (ans.front() < N){
            while (ans.back() >= N) ans.pop_back();
            rep(i, 0, ans.size()){
                if (i) cout << " ";
                cout << ans[i] + 1;
            }
            cout << "\n";
            return;
        }
        vector<int> n_ans;
        pair<int, int> mx = {-1, -1};
        for (auto x : ans) for (auto [var, z] : G[x]){
            if (mx < z) mx = z, n_ans.clear();
            if (mx == z) n_ans.push_back(var);
        }
        swap(n_ans, ans);
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    void init();

    int N, M;
    while (cin >> N >> M, N) solve(N, M);
}
accuracy: 1
time_ms: 180
memory_kb: 18388
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (ll i = s; i < (ll)(t); i++)
#define rrep(i, s, t) for(ll i = (ll)(t) - 1; i >= (ll)(s); i--)
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)

#define TT template<typename T>
TT using vec = vector<T>;
template<class T1, class T2> bool chmin(T1 &x, T2 y) { return x > y ? (x = y, true) : false; }
template<class T1, class T2> bool chmax(T1 &x, T2 y) { return x < y ? (x = y, true) : false; }

struct io_setup {
    io_setup() {
        ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        cout << fixed << setprecision(15);
    }
} io_setup;

struct dsu {
    using vi = vector<int>;   
    using vvi = vector<vector<int>>;
    vi par, sz, es;
    int cc;

    vector<array<int,4>> hist;

    dsu(int n) {
        par = vi(n);
        sz = vi(n, 1);
        es = vi(n, 0);
        cc = n;
        iota(all(par), 0);
    }
  
    int leader(int u) {
        if (par[u] != u) {
            return leader(par[u]);
        }    
        return u;
    }
    
    bool same(int a, int b) {
        return leader(a) == leader(b);
    }
    
    bool merge(int a, int b) {
        a = leader(a), b = leader(b);
        if(sz[a] < sz[b]) swap(a, b);

        if(a == b) {
            ++es[a];
            return false;
        }
        else {
            cc--;
            hist.push_back({b,par[b],a,sz[a]});
            par[b] = leader(a);
            sz[a] += sz[b];
            return true;
        }
    }

    void rollback(){
        auto[b,pb,a,sa]=hist.back();
        hist.pop_back();
        par[b]=pb;
        sz[a]=sa;
    }
    //以下、必要な物を書く

    int size(int u) {
        return sz[leader(u)];
    }

    
    int componentcnt() {
        return cc;
    }
    
    int edgecnt(int u) {
        return es[leader(u)];
    }

    vvi groups() {
        int n = par.size();
        vvi ms(n);
        rep(v, 0, n) {
            ms[leader(v)].push_back(v);
        }

        vvi res;
        rep(i, 0, n) if(ms[i].size() > 0) {
            res.push_back(ms[i]);
        }

        return res;
    }
};
int Solve(){
    int n,m;
    cin>>n>>m;
    if(n==0) return 0;
    vector<vector<array<int,2>>> vv;
    {
        map<int,vector<array<int,2>>> mp;
        rep(i,0,m){
            int a,b,s;
            cin>>a>>b>>s;
            a--, b--;
            mp[s].push_back({a,b});
        }
        for(auto[s,v]:mp) vv.push_back(v);
    }
    m=vv.size();
    dsu uf(n);
    {
        vector<vector<array<int,2>>> nvv;
        for(int i=m-1;i>=0;i--){
            vector<array<int,2>> tmp;
            for(auto[x,y]:vv[i]) if(uf.merge(x,y)) tmp.push_back({x,y});
            reverse(tmp.begin(),tmp.end());
            if(!tmp.empty()) nvv.push_back(tmp);
        }
        reverse(nvv.begin(),nvv.end());
        swap(nvv,vv);
    }
    set<int> lds={uf.leader(0)};
    for(auto vp:vv){
        set<int> cld=lds;
        for(auto[x,y]:vp){
            if(cld.count(uf.leader(x))){
                uf.rollback();
                cld.insert(uf.leader(x));
                cld.insert(uf.leader(y));
            }else{
                uf.rollback();
            }
        }
        int mx=0;
        for(int d:cld) chmax(mx,uf.size(d));
        set<int> nst;
        for(int d:cld){
            if(mx==uf.size(d)) nst.insert(d);
        }
        lds=nst;
    }
    vector<int> ans;
    for(int x:lds) ans.push_back(x+1);
    rep(i,0,ans.size()) cout<<ans[i]<<" \n"[i==ans.size()-1];
    return 1;
}

int main(){
    while(Solve());
}
accuracy: 1
time_ms: 150
memory_kb: 22372
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;

namespace noya2 {

template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p){
    os << p.first << " " << p.second;
    return os;
}
template <typename T, typename U>
istream &operator>>(istream &is, pair<T, U> &p){
    is >> p.first >> p.second;
    return is;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v){
    int s = (int)v.size();
    for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i];
    return os;
}
template <typename T>
istream &operator>>(istream &is, vector<T> &v){
    for (auto &x : v) is >> x;
    return is;
}

void in() {}
template <typename T, class... U>
void in(T &t, U &...u){
    cin >> t;
    in(u...);
}

void out() { cout << "\n"; }
template <typename T, class... U, char sep = ' '>
void out(const T &t, const U &...u){
    cout << t;
    if (sizeof...(u)) cout << sep;
    out(u...);
}

template<typename T>
void out(const vector<vector<T>> &vv){
    int s = (int)vv.size();
    for (int i = 0; i < s; i++) out(vv[i]);
}

struct IoSetup {
    IoSetup(){
        cin.tie(nullptr);
        ios::sync_with_stdio(false);
        cout << fixed << setprecision(15);
        cerr << fixed << setprecision(7);
    }
} iosetup_noya2;

const int iinf = 1'000'000'007;
const long long linf = 2'000'000'000'000'000'000LL;
const long long mod998 =  998244353;
const long long mod107 = 1000000007;
const long double pi = 3.14159265358979323;
const vector<int> dx = {0,1,0,-1,1,1,-1,-1};
const vector<int> dy = {1,0,-1,0,1,-1,-1,1};
const string ALP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string alp = "abcdefghijklmnopqrstuvwxyz";
const string NUM = "0123456789";

void yes(){ cout << "Yes\n"; }
void no(){ cout << "No\n"; }
void YES(){ cout << "YES\n"; }
void NO(){ cout << "NO\n"; }
void yn(bool t){ t ? yes() : no(); }
void YN(bool t){ t ? YES() : NO(); }


unsigned long long inner_binary_gcd(unsigned long long a, unsigned long long b){
    if (a == 0 || b == 0) return a + b;
    int n = __builtin_ctzll(a); a >>= n;
    int m = __builtin_ctzll(b); b >>= m;
    while (a != b) {
        int mm = __builtin_ctzll(a - b);
        bool f = a > b;
        unsigned long long c = f ? a : b;
        b = f ? b : a;
        a = (c - b) >> mm;
    }
    return a << min(n, m);
}

template<typename T> T gcd_fast(T a, T b){ return static_cast<T>(inner_binary_gcd(abs(a),abs(b))); }

long long sqrt_fast(long long n) {
    if (n <= 0) return 0;
    long long x = sqrt(n);
    while ((x + 1) * (x + 1) <= n) x++;
    while (x * x > n) x--;
    return x;
}

template<typename T> T floor_div(const T n, const T d) {
    assert(d != 0);
    return n / d - static_cast<T>((n ^ d) < 0 && n % d != 0);
}

template<typename T> T ceil_div(const T n, const T d) {
    assert(d != 0);
    return n / d + static_cast<T>((n ^ d) >= 0 && n % d != 0);
}

template<typename T> void uniq(vector<T> &v){
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
}

template <typename T, typename U> inline bool chmin(T &x, U y) { return (y < x) ? (x = y, true) : false; }

template <typename T, typename U> inline bool chmax(T &x, U y) { return (x < y) ? (x = y, true) : false; }

template<typename T> inline bool range(T l, T x, T r){ return l <= x && x < r; }

} // namespace noya2

#define rep(i,n) for (int i = 0; i < (int)(n); i++)
#define repp(i,m,n) for (int i = (m); i < (int)(n); i++)
#define reb(i,n) for (int i = (int)(n-1); i >= 0; i--)
#define all(v) (v).begin(),(v).end()

using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull = unsigned long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using pil = pair<int,ll>;
using pli = pair<ll,int>;

namespace noya2{

/*　~ (. _________ . /)　*/

}

using namespace noya2;

struct dsu {
  public:
    dsu() : _n(0) {}
    explicit dsu(int n) : _n(n), parent_or_size(n, -1) {}

    int merge(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        int x = leader(a), y = leader(b);
        if (x == y) return x;
        if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
        parent_or_size[x] += parent_or_size[y];
        parent_or_size[y] = x;
        return x;
    }

    bool same(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        return leader(a) == leader(b);
    }

    int leader(int a) {
        assert(0 <= a && a < _n);
        if (parent_or_size[a] < 0) return a;
        return parent_or_size[a] = leader(parent_or_size[a]);
    }

    int size(int a) {
        assert(0 <= a && a < _n);
        return -parent_or_size[leader(a)];
    }

    std::vector<std::vector<int>> groups() {
        std::vector<int> leader_buf(_n), group_size(_n);
        for (int i = 0; i < _n; i++) {
            leader_buf[i] = leader(i);
            group_size[leader_buf[i]]++;
        }
        std::vector<std::vector<int>> result(_n);
        for (int i = 0; i < _n; i++) {
            result[i].reserve(group_size[i]);
        }
        for (int i = 0; i < _n; i++) {
            result[leader_buf[i]].push_back(i);
        }
        result.erase(
            std::remove_if(result.begin(), result.end(),
                           [&](const std::vector<int>& v) { return v.empty(); }),
            result.end());
        return result;
    }

  private:
    int _n;
    // root node: -1 * component size
    // otherwise: parent
    std::vector<int> parent_or_size;
};

void solve(int n, int m){
    vector<pii> uvs(m);
    vector<int> w(m);
    rep(i,m){
        int u, v; in(u,v); u--, v--;
        uvs[i] = {u,v};
        in(w[i]);
    }
    vector<int> ids(m); iota(all(ids),0);
    ranges::sort(ids, {}, [&](int i){
        return -w[i];
    });
    vector<int> top(n); iota(all(top),0);
    dsu d(n);
    int vid = n;
    vector<int> a(n*2);
    rep(i,n){
        a[i] = iinf;
    }
    vector<vector<int>> childs(n*2);
    vector<int> sz(n*2,1);
    for (int i : ids){
        auto [u, v] = uvs[i];
        if (d.same(u,v)) continue;
        u = d.leader(u);
        v = d.leader(v);
        int uv = d.merge(u,v);
        u = top[u];
        v = top[v];
        int nv = vid++;
        childs[nv].emplace_back(u);
        childs[nv].emplace_back(v);
        top[uv] = nv;
        a[nv] = w[i];
        sz[nv] = sz[u] + sz[v];
        // out(u,v,nv);
    }
    // out(sz);
    // out(a);
    using dat = array<int,3>;
    set<dat> st;
    st.insert({sz[vid-1],a[vid-1],vid-1});
    while (true){
        assert(!st.empty());
        int msz = (*st.rbegin())[0];
        while ((*st.begin())[0] < msz){
            st.erase(st.begin());
        }
        // out(msz);
        int iw = (*st.begin())[1];
        if (iw == iinf){
            vector<int> ans;
            for (auto [p, q, r] : st){
                ans.emplace_back(r+1);
            }
            out(ans);
            return ;
        }
        queue<int> que;
        while (!st.empty() && (*st.begin())[1] == iw){
            auto [p, q, r] = *st.begin();
            que.push(r);
            // out("que",r);
            st.erase(st.begin());
        }
        while (!que.empty()){
            int v = que.front(); que.pop();
            // out("pop",v);
            assert(v >= n);
            for (int c : childs[v]){
                // out("child",v,c,a[c],iw);
                if (a[c] == iw){
                    que.push(c);
                }
                else {
                    st.insert({sz[c],a[c],c});
                }
            }
        }
    }
}

int main(){
    while (true){
        int n, m; in(n,m);
        if (n == 0) break;
        solve(n,m);
    }
}
accuracy: 1
time_ms: 90
memory_kb: 15072
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(a) (a).begin(), (a).end()
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rrep(i, n) for (int i = (int)(n); i >= 0; i--)
#define range(i, l, r) for (int i = (int)(l); i < (int)(r); i++)
using ll = long long;

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "[";
    for (int i = 0; i < v.size(); i++) {
        os << v[i] << (i == (v.size() - 1) ? "" : ", ");
    }
    os << "]";
    return os;
}

template <typename T1, typename T2>
ostream& operator<<(ostream& os, const pair<T1, T2> p) {
    os << "{" << p.first << ", " << p.second << "}";
    return os;
}

struct RollbackUnionFind {
    vector<int> data;
    stack<pair<int, int>> history;
    int inner_snap;

    RollbackUnionFind(int sz) : inner_snap(0) { data.assign(sz, -1); }

    bool unite(int x, int y) {
        x = find(x), y = find(y);
        history.emplace(x, data[x]);
        history.emplace(y, data[y]);
        if (x == y) return false;
        if (data[x] > data[y]) swap(x, y);
        data[x] += data[y];
        data[y] = x;
        return true;
    }

    int find(int k) {
        if (data[k] < 0) return k;
        return find(data[k]);
    }

    int same(int x, int y) { return find(x) == find(y); }

    int size(int k) { return (-data[find(k)]); }

    void undo() {
        data[history.top().first] = history.top().second;
        history.pop();
        data[history.top().first] = history.top().second;
        history.pop();
    }

    void snapshot() { inner_snap = int(history.size() >> 1); }

    int get_state() { return int(history.size() >> 1); }

    void rollback(int state = -1) {
        if (state == -1) state = inner_snap;
        state <<= 1;
        assert(state <= (int)history.size());
        while (state < (int)history.size()) undo();
    }
};

/**
 * @brief RollbackつきUnion Find
 * @docs docs/data-structure/rollback-union-find.md
 */

int main() {
    while (true) {
        int n, m;
        cin >> n >> m;
        if (n == 0) break;

        if (n == 1) {
            cout << 1 << endl;
            continue;
        }

        vector<array<int, 3>> e{};
        e.push_back({0, 1, 0});
        rep(_, m) {
            int a, b, s;
            cin >> a >> b >> s;
            a--;
            b--;
            e.push_back({s, a, b});
        }

        sort(all(e));
        RollbackUnionFind uf(n);
        rrep(i, e.size() - 1) { uf.unite(e[i][1], e[i][2]); }

        set<array<int, 2>> st{};
        st.insert({n, uf.find(0)});

        rep(i, e.size()) {
            if (i > 0 && e[i][0] != e[i - 1][0]) {
                while ((*st.begin())[0] != (*st.rbegin())[0])
                    st.erase(st.begin());
            }
            auto [s, a, b] = e[i];
            int r = uf.find(a);
            int sz = uf.size(a);

            uf.undo();
            if (sz == uf.size(a)) continue;
            if (st.find({sz, r}) == st.end()) continue;
            st.erase({sz, r});
            st.insert({uf.size(a), uf.find(a)});
            st.insert({uf.size(b), uf.find(b)});
        }

        vector<int> ans{};
        auto it = st.begin();
        while (it != st.end()) {
            ans.push_back((*it)[1]);
            it++;
        }

        rep(i, ans.size()) {
            cout << ans[i] + 1 << (i == ans.size() - 1 ? "\n" : " ");
        }
    }
}
accuracy: 1
time_ms: 200
memory_kb: 6684
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

struct UnionFind {
    vector<vector<int>> vers;
    vector<int> leader;
    
    vector<vector<pair<int, int>>> op;
    vector<vector<int>> minimas;

    UnionFind(int n) {
        leader.resize(n);
        vers.resize(n);
        op.resize(n);
        minimas.resize(n);
        iota(all(leader), 0);
        rep(i, n) {
            vers[i].pb(i);
            op[i].push_back({1 << 20, 1});
            minimas[i].pb(i);
        }
    }
    int judge(int x, int y, int t) {
        if(op[x].back().first == t) op[x].pop_back();
        if(op[y].back().first == t) op[y].pop_back();
        int sz1 = op[x].size();
        int sz2 = op[y].size();
        int sz = min(sz1, sz2);
        for(int i = 1; i <= sz; i ++) {
            auto [t1, s1] = op[x][sz1 - i];
            auto [t2, s2] = op[y][sz2 - i];
            if(s1 == s2) {
                if(t1 > t2) {
                    return -1;
                } else if(t1 < t2) {
                    return 1;
                } 
            } else {
                if(s1 < s2) {
                    return 1;
                } else {
                    return -1;
                }
            }
        }
        return 0;
    }
    void connect(int x, int y, int s) {
        x = leader[x]; y = leader[y];
        if (x == y) return;
        if(vers[x].size() < vers[y].size()) swap(x, y);
        int flag = judge(x, y, s);
        if(flag == -1) { 
            ;
        } else if(flag == 1) {
            op[x] = op[y];
            minimas[x] = minimas[y];
        } else {
            if(minimas[x].size() < minimas[y].size()) {
                foa(e, minimas[x]) {
                    minimas[y].pb(e);
                }
                minimas[x] = minimas[y];
            } else {
                foa(e, minimas[y]) {
                    minimas[x].pb(e);
                }
                minimas[y].clear();
            }
        }
        foa(e, vers[y]) {
            leader[e] = x;
            vers[x].pb(e);
        }
        op[x].push_back({s, (int)vers[x].size()});
        return;
    }
};

int main() {
    int n, m; 
    cin >> n >> m;
    while(n) {
        vector<tuple<int, int, int>> edges;
        rep(i, m) {
            int x, y, s; cin >> x >> y >> s;
            x --; y --;
            edges.push_back({s, x, y});
        }
        sort(all(edges));
        reverse(all(edges));
        UnionFind uf(n);
        for(auto [s, x, y] : edges) {
            uf.connect(x, y, s);
        }
        auto ans = uf.minimas[uf.leader[0]];
        sort(all(ans));
        int sz = ans.size();
        rep(i, sz) {
            if(i) cout << " ";
            cout << ans[i] + 1;
        }
        cout << endl;
        cin >> n >> m;
    }
    return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 23540
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

struct UnionFind {
    vector<vector<int>> vers;
    vector<int> leader;
    
    vector<vector<pair<int, int>>> op;
    vector<vector<int>> minimas;

    UnionFind(int n) {
        leader.resize(n);
        vers.resize(n);
        op.resize(n);
        minimas.resize(n);
        iota(all(leader), 0);
        rep(i, n) {
            vers[i].pb(i);
            op[i].push_back({1 << 20, 1});
            minimas[i].pb(i);
        }
    }
    int judge(int x, int y, int t) {
        if(op[x].back().first == t) op[x].pop_back();
        if(op[y].back().first == t) op[y].pop_back();
        int sz1 = op[x].size();
        int sz2 = op[y].size();
        int sz = min(sz1, sz2);
        for(int i = 1; i <= sz; i ++) {
            auto [t1, s1] = op[x][sz1 - i];
            auto [t2, s2] = op[y][sz2 - i];
            if(s1 == s2) {
                if(t1 > t2) {
                    return -1;
                } else if(t1 < t2) {
                    return 1;
                } 
            } else {
                if(s1 < s2) {
                    return 1;
                } else {
                    return -1;
                }
            }
        }
        return 0;
    }
    void connect(int x, int y, int s) {
        x = leader[x]; y = leader[y];
        if (x == y) return;
        if(vers[x].size() < vers[y].size()) swap(x, y);
        int flag = judge(x, y, s);
        if(flag == -1) { 
            ;
        } else if(flag == 1) {
            op[x] = op[y];
            minimas[x] = minimas[y];
        } else {
            if(minimas[x].size() < minimas[y].size()) {
                foa(e, minimas[x]) {
                    minimas[y].pb(x);
                }
                minimas[x] = minimas[y];
            } else {
                foa(e, minimas[y]) {
                    minimas[x].pb(e);
                }
                minimas[y].clear();
            }
        }
        foa(e, vers[y]) {
            leader[e] = x;
            vers[x].pb(e);
        }
        op[x].push_back({s, (int)vers[x].size()});
        return;
    }
};

int main() {
    int n, m; 
    cin >> n >> m;
    while(n) {
        vector<tuple<int, int, int>> edges;
        rep(i, m) {
            int x, y, s; cin >> x >> y >> s;
            x --; y --;
            edges.push_back({s, x, y});
        }
        sort(all(edges));
        reverse(all(edges));
        UnionFind uf(n);
        for(auto [s, x, y] : edges) {
            uf.connect(x, y, s);
        }
        auto ans = uf.minimas[uf.leader[0]];
        sort(all(ans));
        int sz = ans.size();
        rep(i, sz) {
            if(i) cout << " ";
            cout << ans[i] + 1;
        }
        cout << endl;
        cin >> n >> m;
    }
    return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 23536
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

struct UnionFind {
    vector<vector<int>> vers;
    vector<int> leader;
    
    vector<vector<pair<int, int>>> op;
    vector<vector<int>> minimas;

    UnionFind(int n) {
        leader.resize(n);
        vers.resize(n);
        op.resize(n);
        minimas.resize(n);
        iota(all(leader), 0);
        rep(i, n) {
            vers[i].pb(i);
            op[i].push_back({1 << 20, 1});
            minimas[i].pb(i);
        }
    }
    int judge(int x, int y, int t) {
        if(op[x].back().first == t) op[x].pop_back();
        if(op[y].back().first == t) op[y].pop_back();
        int sz1 = op[x].size();
        int sz2 = op[y].size();
        int sz = min(sz1, sz2);
        for(int i = 1; i <= sz; i ++) {
            auto [t1, s1] = op[x][sz1 - i];
            auto [t2, s2] = op[y][sz2 - i];
            if(s1 == s2) {
                if(t1 > t2) {
                    return -1;
                } else if(t1 < t2) {
                    return 1;
                } 
            } else {
                if(s1 < s2) {
                    return 1;
                } else {
                    return -1;
                }
            }
        }
        return 0;
    }
    void connect(int x, int y, int s) {
        x = leader[x]; y = leader[y];
        if (x == y) return;
        if(vers[x].size() < vers[y].size()) swap(x, y);
        int flag = judge(x, y, s);
        if(flag == -1) { 
            ;
        } else if(flag == 1) {
            op[x] = (op[y]);
            minimas[x] = (minimas[y]);
        } else {
            if(minimas[x].size() < minimas[y].size()) {
                foa(e, minimas[x]) {
                    minimas[y].pb(x);
                }
                minimas[x] = (minimas[y]);
            } else {
                foa(e, minimas[y]) {
                    minimas[x].pb(e);
                }
                minimas[y].clear();
            }
        }
        foa(e, vers[y]) {
            leader[e] = x;
            vers[x].pb(e);
        }
        op[x].push_back({s, (int)vers[x].size()});
        return;
    }
};

int main() {
    int n, m; 
    cin >> n >> m;
    while(n) {
        vector<tuple<int, int, int>> edges;
        rep(i, m) {
            int x, y, s; cin >> x >> y >> s;
            x --; y --;
            edges.push_back({s, x, y});
        }
        sort(all(edges));
        reverse(all(edges));
        UnionFind uf(n);
        for(auto [s, x, y] : edges) {
            uf.connect(x, y, s);
        }
        auto ans = uf.minimas[uf.leader[0]];
        sort(all(ans));
        int sz = ans.size();
        rep(i, sz) {
            if(i) cout << " ";
            cout << ans[i] + 1;
        }
        cout << endl;
        cin >> n >> m;
    }
    return 0;
}
accuracy: 1
time_ms: 290
memory_kb: 23228
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

struct UnionFind {
    vector<vector<int>> vers;
    vector<int> leader;
    
    vector<vector<pair<int, int>>> op;
    vector<vector<int>> minimas;

    UnionFind(int n) {
        leader.resize(n);
        vers.resize(n);
        op.resize(n);
        minimas.resize(n);
        iota(all(leader), 0);
        rep(i, n) {
            vers[i].pb(i);
            op[i].push_back({1 << 20, 1});
            minimas[i].pb(i);
        }
    }
    int judge(int x, int y, int t) {
        if(op[x].back().first == t) op[x].pop_back();
        if(op[y].back().first == t) op[y].pop_back();
        int sz1 = op[x].size();
        int sz2 = op[y].size();
        int sz = min(sz1, sz2);
        for(int i = 1; i <= sz; i ++) {
            auto [t1, s1] = op[x][sz1 - i];
            auto [t2, s2] = op[y][sz2 - i];
            if(s1 == s2) {
                if(t1 > t2) {
                    return -1;
                } else if(t1 < t2) {
                    return 1;
                } 
            } else {
                if(s1 < s2) {
                    return 1;
                } else {
                    return -1;
                }
            }
        }
        return 0;
    }
    void connect(int x, int y, int s) {
        x = leader[x]; y = leader[y];
        if (x == y) return;
        if(vers[x].size() < vers[y].size()) swap(x, y);
        int flag = judge(x, y, s);
        if(flag == -1) { 
            ;
        } else if(flag == 1) {
            op[x] = move(op[y]);
            minimas[x] = move(minimas[y]);
        } else {
            if(minimas[x].size() < minimas[y].size()) {
                foa(e, minimas[x]) {
                    minimas[y].pb(x);
                }
                minimas[x] = move(minimas[y]);
            } else {
                foa(e, minimas[y]) {
                    minimas[x].pb(e);
                }
                minimas[y].clear();
            }
        }
        foa(e, vers[y]) {
            leader[e] = x;
            vers[x].pb(e);
        }
        op[x].push_back({s, (int)vers[x].size()});
        return;
    }
};

int main() {
    int n, m; 
    cin >> n >> m;
    while(n) {
        vector<tuple<int, int, int>> edges;
        rep(i, m) {
            int x, y, s; cin >> x >> y >> s;
            x --; y --;
            edges.push_back({s, x, y});
        }
        sort(all(edges));
        reverse(all(edges));
        UnionFind uf(n);
        for(auto [s, x, y] : edges) {
            uf.connect(x, y, s);
        }
        auto ans = uf.minimas[uf.leader[0]];
        sort(all(ans));
        int sz = ans.size();
        rep(i, sz) {
            if(i) cout << " ";
            cout << ans[i] + 1;
        }
        cout << endl;
        cin >> n >> m;
    }
    return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 23528
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

struct UnionFind {
    vector<vector<int>> vers;
    vector<int> leader;
    
    vector<vector<pair<int, int>>> op;
    vector<int> op_leader;

    vector<vector<int>> minimas;
    vector<int> minimas_leader;

    UnionFind(int n) {
        leader.resize(n);
        vers.resize(n);
        op.resize(n);
        op_leader.resize(n);
        minimas.resize(n);
        minimas_leader.resize(n);
        iota(all(leader), 0);
        iota(all(op_leader), 0);
        iota(all(minimas_leader), 0);
        rep(i, n) {
            vers[i].pb(i);
            op[i].push_back({1 << 20, 1});
            minimas[i].pb(i);
        }
    }
    int judge(int x, int y, int t) {
        x = op_leader[x];
        y = op_leader[y];
        if(op[x].back().first == t) op[x].pop_back();
        if(op[y].back().first == t) op[y].pop_back();
        int sz1 = op[x].size();
        int sz2 = op[y].size();
        int sz = min(sz1, sz2);
        for(int i = 1; i <= sz; i ++) {
            auto [t1, s1] = op[x][sz1 - i];
            auto [t2, s2] = op[y][sz2 - i];
            if(s1 == s2) {
                if(t1 > t2) {
                    return -1;
                } else if(t1 < t2) {
                    return 1;
                } 
            } else {
                if(s1 < s2) {
                    return 1;
                } else {
                    return -1;
                }
            }
        }
        return 0;
    }
    void connect(int x, int y, int s) {
        x = leader[x]; y = leader[y];
        if (x == y) return;
        if(vers[x].size() < vers[y].size()) swap(x, y);
        int flag = judge(x, y, s);
        if(flag == -1) { 
            ;
        } else if(flag == 1) {
            op_leader[x] = op_leader[y];
            minimas_leader[x] = minimas_leader[y];
        } else {
            int x0 = minimas_leader[x], y0 = minimas_leader[y];
            if(minimas[x0].size() < minimas[y0].size()) {
                foa(e, minimas[x0]) minimas[y0].pb(e);
                minimas_leader[x] = y0;
            } else {
                foa(e, minimas[y0]) minimas[x0].pb(e);
                minimas_leader[y] = x0;
            }
        }
        foa(e, vers[y]) {
            leader[e] = x;
            vers[x].pb(e);
        }
        op[op_leader[x]].push_back({s, (int)vers[x].size()});
        return;
    }
    vector<int> get_minima(int x) {
        x = leader[x];
        x = minimas_leader[x];
        return minimas[x];
    }
};

int main() {
    int n, m; 
    cin >> n >> m;
    while(n) {
        vector<tuple<int, int, int>> edges;
        rep(i, m) {
            int x, y, s; cin >> x >> y >> s;
            x --; y --;
            edges.push_back({s, x, y});
        }
        sort(all(edges));
        reverse(all(edges));
        UnionFind uf(n);
        for(auto [s, x, y] : edges) {
            uf.connect(x, y, s);
        }
        assert((int)uf.vers[uf.leader[0]].size() == n);
        auto ans = uf.get_minima(0);
        sort(all(ans));
        int sz = ans.size();
        rep(i, sz) {
            if(i) cout << " ";
            cout << ans[i] + 1;
        }
        cout << endl;
        cin >> n >> m;
    }
    return 0;
}
accuracy: 1
time_ms: 300
memory_kb: 24088
final_rank: 15

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
using i64 = long long;
#define rep(i,n) for(i64 i=0; i<i64(n); i++)

struct Dsu {
    vector<i64> A;
    Dsu(i64 n = 0) : A(n,-1) {}
    i64 leader(i64 a){
        if(A[a] < 0) return a;
        return A[a] = leader(A[a]);
    }
    void merge(i64 u, i64 v){
        u = leader(u);
        v = leader(v);
        if(-A[u] < -A[v]) swap(u, v);
        A[u] += A[v];
        A[v] = u;
    }
};

void testcase(){
    i64  N, M; cin >> N >> M;
    if(N == 0) exit(0);
    vector<pair<i64,pair<i64,i64>>> joins;
    rep(i,M){
        i64 a,b,s; cin >> a >> b >> s; a--; b--;
        joins.push_back({ s, {a,b} });
    }
    sort(joins.rbegin(), joins.rend());
    vector<i64> sz(N,1), st(N,1000000000), id(N);
    vector<vector<i64>> ch(N);
    rep(i,N) id[i] = i;
    auto dsu = Dsu(N);
    for(auto [s,uv] : joins){
        auto [u,v] = uv;
        if(dsu.leader(u) == dsu.leader(v)) continue;
        i64 x = id[dsu.leader(u)];
        i64 y = id[dsu.leader(v)];
        dsu.merge(u,v);
        if(st[y] == s) swap(x,y);
        if(st[y] == s){
            if(ch[x].size() < ch[y].size()) swap(x,y);
            for(auto a : ch[y]) ch[x].push_back(a);
            if(y < N) ch[x].push_back(y);
            ch[y] = {};
            sz[x] += sz[y];
            id[dsu.leader(u)] = x;
        } else if(st[x] == s){
            ch[x].push_back(y);
            sz[x] += sz[y];
            id[dsu.leader(u)] = x;
        } else {
            i64 z = sz.size();
            sz.push_back(sz[x] + sz[y]);
            st.push_back(s);
            ch.push_back({ x,y });
            id[dsu.leader(u)] = z;
        }
    }
    vector<i64> cand;
    cand.push_back(id[dsu.leader(0)]);
    while(cand[0] >= N){
        i64 s = -1, z = 0;
        for(i64 a : cand) for(auto b : ch[a]){
            if(z < sz[b] || (z == sz[b] && s < st[b])){
                s = st[b]; z = sz[b];
            }
        }
        vector<i64> nxcand;
        for(i64 a : cand) for(auto b : ch[a]){
            if(s == st[b] && z == sz[b]) nxcand.push_back(b);
        }
        swap(cand, nxcand);
    }
    sort(cand.begin(), cand.end());
    rep(i,cand.size()){
        if(i) cout << " ";
        cout << (1 + cand[i]);
    } cout << "\n";
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while(true) testcase();
    return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 20500
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep2(i, n) for (ll i = 0; i < (n); i++)
#define rep3(i, a, b) for (ll i = (a); i < (b); i++)
#define overload(a, b, c, d, ...) d
#define rep(...) overload(__VA_ARGS__, rep3, rep2)(__VA_ARGS__)
#define all(a) begin(a), end(a)
bool chmin(auto& a, auto b) { return a > b ? a = b, 1 : 0; }
bool chmax(auto& a, auto b) { return a < b ? a = b, 1 : 0; }

struct UnionFind {
    int n;
    vector<int> a;
    UnionFind(int n): n(n), a(n, -1) {}
    int find(int x) {
        if (a[x] < 0) return x;
        return a[x] = find(a[x]);
    }
    bool merge(int l, int r) {
        l = find(l);
        r = find(r);
        if (l == r) return false;
        if (a[l] < a[r]) swap(l, r);
        a[r] += a[l];
        a[l] = r;
        return true;
    }
    int size(int i) {
        return -a[find(i)];
    }
};

int solve() {
    int n, m;
    cin >> n >> m;
    if (n == 0) return 1;
    vector<tuple<int, int, int>> edges;
    rep(i, m) {
        int a, b, s;
        cin >> a >> b >> s;
        a--; b--;
        edges.emplace_back(a, b, s);
    }
    sort(all(edges), [&](auto lhs, auto rhs) {
        return get<2>(lhs) > get<2>(rhs);
    });
    // size, root
    using P = pair<int, int>;
    // Big, lhs, rhs
    vector<tuple<P, P, P>> info;
    {
        UnionFind uf(n);
        vector<tuple<int, int, int>> temp;
        for (auto [u, v, s]: edges) {
            int l = uf.find(u);
            int r = uf.find(v);
            int ls = uf.size(l);
            int rs = uf.size(r);
            if (uf.merge(u, v)) {
                temp.emplace_back(u, v, s);
                int m = uf.find(u);
                info.emplace_back(P{uf.size(m), m}, P{ls, l}, P{rs, r});
            }
        }
        edges = temp;
    }
    reverse(all(info));
    reverse(all(edges));
    // (size, root)
    set<P> S;
    if (edges.empty()) {
        S.emplace(1, 0);
    } else {
        S.emplace(n, get<0>(info[0]).second);
    }
    for (int L = 0, R = 0; L + 1 < n; L = R) {
        while (R + 1 < n && get<2>(edges[L]) == get<2>(edges[R])) R++;
        rep(i, L, R) {
            auto [root, lhs, rhs] = info[i];
            if (!S.contains(root)) continue;
            S.erase(root);
            S.insert(lhs);
            S.insert(rhs);
        }
        while (true) {
            auto sit = S.begin();
            auto eit = prev(S.end());
            if (sit->first != eit->first) {
                S.erase(sit);
            } else {
                break;
            }
        }
    }

    vector<int> ans;
    for (auto [s, u]: S) ans.push_back(u);
    rep(i, ssize(ans)) cout << ans[i] + 1 << " \n"[i + 1 == ssize(ans)];

    return 0;
}

int main() {
    cin.tie(0)->sync_with_stdio(0);
    while (!solve());
}
accuracy: 1
time_ms: 80
memory_kb: 13472
final_rank: 2

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

struct dsu {
  public:
    dsu() : _n(0) {}
    dsu(int n) : _n(n), parent_or_size(n, -1) {}

    int merge(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        int x = leader(a), y = leader(b);
        if (x == y) return x;
        if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
        parent_or_size[x] += parent_or_size[y];
        parent_or_size[y] = x;
        return x;
    }

    bool same(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        return leader(a) == leader(b);
    }

    int leader(int a) {
        assert(0 <= a && a < _n);
        if (parent_or_size[a] < 0) return a;
        return parent_or_size[a] = leader(parent_or_size[a]);
    }

    int size(int a) {
        assert(0 <= a && a < _n);
        return -parent_or_size[leader(a)];
    }

    std::vector<std::vector<int>> groups() {
        std::vector<int> leader_buf(_n), group_size(_n);
        for (int i = 0; i < _n; i++) {
            leader_buf[i] = leader(i);
            group_size[leader_buf[i]]++;
        }
        std::vector<std::vector<int>> result(_n);
        for (int i = 0; i < _n; i++) {
            result[i].reserve(group_size[i]);
        }
        for (int i = 0; i < _n; i++) {
            result[leader_buf[i]].push_back(i);
        }
        result.erase(
            std::remove_if(result.begin(), result.end(),
                           [&](const std::vector<int>& v) { return v.empty(); }),
            result.end());
        return result;
    }

  private:
    int _n;
    // root node: -1 * component size
    // otherwise: parent
    std::vector<int> parent_or_size;
};

int MAXS = 100010;

struct Edge {
    int a, b;
    int sza, szb;
};

void BFS(int X, int H, vector<vector<pair<int,int>>>& G, vector<bool>& ANS) {
    int N = ANS.size();
    queue<int> Q;
    Q.push(X);
    ANS[X] = false;
    while(!Q.empty()) {
        int P = Q.front();
        Q.pop();
        for (pair<int,int> p : G[P]) {
            auto [NP,s] = p;
            if (s <= H) continue;
            if (ANS[NP]) {
                ANS[NP] = false;
                Q.push(NP);
            }
        }
    } 
    return;
}

int main() {
while(1) {
    int N, M;
    cin >> N >> M;
    if (N == 0 && M == 0) return 0;
    vector<vector<pair<int,int>>> G(N);
    vector<vector<pair<int,int>>> OldS(MAXS);
    vector<vector<Edge>> S(MAXS);
    rep(i,0,M) {
        int a, b, s;
        cin >> a >> b >> s;
        a--, b--;
        OldS[s].push_back({a,b});
    }
    dsu UF(N);
    rrep(i,0,MAXS) {
        for (pair<int,int> p : OldS[i]) {
            auto [a,b] = p;
            if (UF.same(a,b)) continue;
            G[a].push_back({b,i});
            G[b].push_back({a,i});
            int sza = UF.size(a), szb = UF.size(b);
            S[i].push_back({a,b,sza,szb});
            UF.merge(a,b);
        }
    }
    vector<bool> ANS(N,true);
    multiset<int> ST;
    ST.insert(N);
    rep(i,0,MAXS) reverse(ALL(S[i]));
    rep(i,0,MAXS) {
        if (S[i].empty()) continue;
        for (Edge E : S[i]) {
            if (!ANS[E.a] || !ANS[E.b]) continue;
            ST.erase(ST.find(E.sza+E.szb));
            ST.insert(E.sza);
            ST.insert(E.szb);
        }
        int MAX = *ST.rbegin();
        for (Edge E : S[i]) {
            if (E.sza < MAX) BFS(E.a,i,G,ANS);
            if (E.szb < MAX) BFS(E.b,i,G,ANS);
        }
        while(*ST.begin() < MAX) ST.erase(ST.begin());
    }
    vector<int> ANS2;
    rep(i,0,N) {
        if (ANS[i]) ANS2.push_back(i);
    }
    rep(i,0,ANS2.size()) {
        cout << ANS2[i] + 1 << (i + 1 == ANS2.size() ? '\n' : ' ');
    }
}
}
accuracy: 1
time_ms: 310
memory_kb: 20000
final_rank: 7

code_snippet: #include<bits/stdc++.h>
// #include<atcoder/all>
// #include<boost/multiprecision/cpp_int.hpp>

using namespace std;
// using namespace atcoder;
// using bint = boost::multiprecision::cpp_int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using P = pair<ll,ll>;
using vi = vector<ll>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using ve = vector<vector<int>>;
using vb = vector<bool>;
using vvb = vector<vb>;
#define rep(i,n) for(ll i = 0;i < (ll)n;i++)
#define ALL(x) (x).begin(),(x).end()
#define sz(c) ((ll)(c).size())
#define LB(A,x) (int)(lower_bound(A.begin(),A.end(),x)-A.begin())
#define UB(A,x) (int)(upper_bound(A.begin(),A.end(),x)-A.begin())
// #define MOD 1000000007
#define MOD 998244353
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){for(int i = 0;i < v.size();i++)os<<v[i]<<(i+1!=v.size()?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.first<<" "<<p.second;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T> inline bool chmax(T &a,T b){if(a < b){a = b;return true;}return false;}
template<typename T> inline bool chmin(T &a,T b){if(a > b){a = b;return true;}return false;}
ld dist(ld x1,ld y1,ld x2, ld y2){return sqrtl((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}


// https://ei1333.github.io/luzhiled/snippets/structure/union-find.html
struct UnionFindUndo{
  vector<int> par;
  stack<pair<int,int>> history;
  UnionFindUndo(int n):par(n,-1){}
  // O(logN)

  bool unite(int x,int y){
    x = root(x),y = root(y);
    history.emplace(x, par[x]);
    history.emplace(y, par[y]);
    if(x == y) return false;
    if(par[x] > par[y]) swap(x, y);
    par[x] += par[y];
    par[y] = x;
    return true;
  }
  bool find(int x,int y){
    return root(x) == root(y);
  }
  int root(int x){
    return par[x] < 0 ? x : root(par[x]);
  }
  int size(int x){
    return -par[root(x)];
  }
  void undo(){
    par[history.top().first] = history.top().second;
    history.pop();
    par[history.top().first] = history.top().second;
    history.pop();
  }
  // ある時点を記録する。その時点よりさかのぼることができなくなる・
  void snapshot(){
    while(history.size())history.pop();
  }
  // 記録した時点にさかのぼる。
  void rollback(){
    while(history.size())undo();
  }
};


int main(){
  
  ios_base::sync_with_stdio(0), cin.tie(0);
  while(1){
    int n,m;cin >> n >> m;
    if(n == 0 && m == 0)break;
    vector<vector<P>> v(100010);
    vvi vv(n),w(n);
    rep(i,m){
      int a,b,c;cin >> a >> b >> c;
      a--;b--;
      v[c].emplace_back(a,b);
      vv[a].emplace_back(b);
      vv[b].emplace_back(a);
      w[a].emplace_back(c);
      w[b].emplace_back(c);
    }
    vi is(n,1);
    UnionFindUndo uf(n);
    for(int i = 100000;i >= 0;i--){
      rep(j,sz(v[i])){
        auto [a,b] = v[i][j];
        uf.unite(a,b);
      }
    }
    auto ch = [&](int k,int i)->void{
      queue<int> que;que.push(k);
      is[k] = 0;
      while(!que.empty()){
        int ov = que.front();que.pop();
        rep(j,sz(vv[ov])){
          int nv = vv[ov][j],c = w[ov][j];
          if(c <= i)continue;
          if(!is[nv])continue;
          is[nv] = 0;
          que.push(nv);
        }
      }
    };
    multiset<int> st;
    st.insert(n);
    rep(i,100010){
      rep(j,sz(v[i])){
        auto [a,b] = v[i][sz(v[i])-1-j];
        int k = uf.size(a);
        uf.undo();
        if(!is[a])continue;
        if(uf.find(a,b))continue;
        st.erase(st.find(k));
        st.insert(uf.size(a));
        st.insert(uf.size(b));
      }
      int mx = *st.rbegin();
      while(1){
        int k = *st.begin();
        if(k < mx)st.erase(st.begin());
        else break;
      }
      rep(j,sz(v[i])){
        auto [a,b] = v[i][j];
        if(uf.size(a) < mx && is[a]){
          ch(a,i);
        }
        if(uf.size(b) < mx && is[b]){
          ch(b,i);
        }
      }
    }
    vi res;
    rep(i,n)if(is[i])res.emplace_back(i+1);
    cout << res << "\n";
  }
  

  return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 22308
final_rank: 8

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<vvb> vvvb;
typedef vector<vvvb> vvvvb;
typedef pair<ll,ll> pi;
typedef pair<ll,pi> ppi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define RFOR(i,l,r) for(ll i=r-1;i>=l;i--)
#define RREP(i,n) RFOR(i,0,n)
#define sz(A) (ll)(A.size())
#define ALL(A) A.begin(),A.end()
#define LB(A,x) (ll)(lower_bound(ALL(A),x)-A.begin())
#define UB(A,x) (ll)(upper_bound(ALL(A),x)-A.begin())
#define COU(A,x) (UB(A,x)-LB(A,x))
#define F first
#define S second
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.F<<" "<<p.S;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.F>>p.S;return is;}
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){REP(i,sz(v))os<<v[i]<<(i+1!=sz(v)?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<class T>bool chmax(T&a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T>bool chmin(T&a,T b){if(b<a){a=b;return 1;}return 0;}
const ll mod=998244353;
template<const long long int mod=998244353>
struct modint{
  using mint=modint<mod>;
  long long int x;
  modint(long long int _x=0):x(_x%mod){if(x<0)x+=mod;}
  long long int val(){return x;}
  mint&operator=(const mint&a){x=a.x;return *this;}
  mint&operator+=(const mint&a){x+=a.x;if(x>=mod)x-=mod;return *this;}
  mint&operator-=(const mint&a){x-=a.x;if(x<0)x+=mod;return *this;}
  mint&operator*=(const mint&a){x*=a.x;x%=mod;return *this;}
  friend mint operator+(const mint&a,const mint&b){return mint(a)+=b;}
  friend mint operator-(const mint&a,const mint&b){return mint(a)-=b;}
  friend mint operator*(const mint&a,const mint&b){return mint(a)*=b;}
  mint operator-()const{return mint(0)-*this;}
  mint pow(long long int n){
    if(!n)return 1;
    mint a=1;
    mint _x=x;
    while(n){
      if(n&1)a*=_x;
      _x=_x*_x;n>>=1;
    }
    return a;
  }
  mint inv(){return pow(mod-2);}
  mint&operator/=(mint&a){return *this*=a.inv();}
  friend mint operator/(const mint&a,mint b){return mint(a)/=b;}
};
using mint=modint<998244353>;
#include<bits/stdc++.h>
using namespace std;
struct dsu{
    private:
	vector<int>parent;
    public:
    dsu()=default;
	  dsu(size_t n):parent(n,-1){}
	  int leader(int i){
		    if(parent[i]<0)return i;
		    return parent[i]<0?i:(parent[i]=leader(parent[i]));
	  }
	  int merge(int a,int b){
		    a=leader(a);
		    b=leader(b);
		    if (a!=b){
			      if(-parent[a]<-parent[b])swap(a,b);
			      parent[a]+=parent[b];
			      parent[b]=a;
		    }
		    return a;
	  }
	  bool same(int a,int b){return leader(a)==leader(b);}
	  int size(int i){return -parent[leader(i)];}
	  vector<vector<int>>groups(){
	      size_t n=parent.size();
	      vector<vector<int>>A(n);
	      for(int i=0;i<n;i++)A[leader(i)].emplace_back(i);
	      vector<vector<int>>res;
	      for(auto a:A)if(a.size())res.emplace_back(a);
	      return res;
	  }
};
int main(){
    while(1){
        int N,M;cin>>N>>M;
        if(!N)return 0;
        vector<vector<pi>>E(1e5);
        REP(i,M){
            ll a,b,s;cin>>a>>b>>s;a--;b--;s--;
            E[s].emplace_back(pi(a,b));
        }
        set<pi>S;
        REP(i,N)S.insert(pi(1,i));
        vector<vector<pair<pi,pair<pi,pi>>>>T(1e5);
        dsu D(N);
        RREP(i,1e5){
            for(auto[a,b]:E[i])if(!D.same(a,b)){
                a=D.leader(a);b=D.leader(b);
                auto p=pi(D.size(a),a);
                auto q=pi(D.size(b),b);
                S.erase(p);S.erase(q);
                ll c=D.merge(a,b);
                T[i].emplace_back(make_pair(pi(D.size(c),c),make_pair(p,q)));
                S.insert(pi(D.size(c),c));
            }
        }
        REP(i,1e5){
            reverse(ALL(T[i]));
            for(auto[p,q]:T[i]){
                if(S.count(p)){
                    S.erase(p);
                    S.insert(q.F);
                    S.insert(q.S);
                }
            }
            ll f=(*prev(S.end())).F;
            while((*S.begin()).F!=f){S.erase(S.begin());}
        }
        vi ans;
        for(auto p:S)ans.emplace_back(p.S+1);
        sort(ALL(ans));
        cout<<ans<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 450
memory_kb: 17920
final_rank: 13

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

template < class T > vector< T >& operator++(vector< T >& a) { for(T& x : a) x++; return a; }
template < class T > vector< T >& operator--(vector< T >& a) { for(T& x : a) x--; return a; }
template < class T > vector< T >  operator++(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x++; return res; }
template < class T > vector< T >  operator--(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x--; return res; }

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

class union_find {
  public:
    union_find(int n) : data(n, -1) {}
    int unite(int x, int y) {
        x = root(x), y = root(y);
        if(x != y) {
            // if(size(x) < size(y)) swap(x, y);
            data[x] += data[y];
            return data[y] = x;
        }
        return -1;
    }
    int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
    int size(int x) { return -data[root(x)]; }
    bool same(int x, int y) { return root(x) == root(y); }

  private:
    vector<int> data;
};


vector<int> solve(int n, int m) {
    map<int, vector<pair<int,int>>> edges;
    for(int _ : rep(m)) {
        int a = in(), b = in(), s = in(); a--, b--;
        edges[-s].push_back({a, b});
    }

    struct D {
        vector<int> vertex;
        vector<int> weight;
        vector<int> size;
        D() {}
    };
    auto cmp = [&](const D& L, const D& R) -> int {
        const int nL = L.weight.size();
        const int nR = R.weight.size();
        int pL = nL - 1;
        int pR = nR - 1;
        while(0 <= pL and 0 <= pR) {
            if(L.size[pL] == R.size[pR]) {
                if(L.weight[pL] == R.weight[pR]) {
                    pL--, pR--;
                } else {
                    return L.weight[pL] > R.weight[pR] ? -1 : +1;
                }
            } else {
                return L.size[pL] > R.size[pR] ? -1 : +1;
            }
        }
        if(pL == -1 and pR == -1) {
            return 0;
        } else {
            return pR == -1 ? -1 : +1;
        }
    };
    
    union_find uf(n);
    vector< D > data(n);
    for(int x : rep(n)) data[x].vertex.push_back(x);
    for(const auto &[s_, es] : edges) {
        const int s = - s_;
        set<int> cand;
        for(const auto &[u, v] : es) {
            int ru = uf.root(u);
            int rv = uf.root(v);
            if(uf.same(ru, rv)) continue;
            int p = uf.unite(ru, rv);
            cand.insert(p);
            const int c = cmp(data[ru], data[rv]);
            if(c == 0) {
                assert(ru == p || rv == p);
                int q = (ru ^ rv ^ p);
                if(data[p].vertex.size() < data[q].vertex.size()) swap(data[p].vertex, data[q].vertex);
                for(int x : data[q].vertex) data[p].vertex.push_back(x);
            } else {
                int q = (c == -1 ? ru : rv);
                swap(data[p].vertex, data[q].vertex);
                swap(data[p].weight, data[q].weight);
                swap(data[p].size  , data[q].size  );
            }
        }
        
        for(int x : cand) if(uf.root(x) == x) {
            data[x].weight.push_back(s);
            data[x].size.push_back(uf.size(x));
        }
    }
    vector<int> ans = data[uf.root(0)].vertex;
    sort(ans);
    ans++;
    return ans;
}

int main() {
    while(true) {
        int n = in(), m = in();
        if(make_pair(n, m) == make_pair(0, 0)) return 0;
        print(solve(n, m));
    }
}
accuracy: 1
time_ms: 210
memory_kb: 27172
final_rank: 16

code_snippet: #include <bits/stdc++.h>
// #include <atcoder/all>
using namespace std;
// using namespace atcoder;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define rrep(i, a, n) for(int i = a; i >= n; i--)
#define inr(l, x, r) (l <= x && x < r)
#define ll long long
#define ld long double

// using mint = modint1000000007;
// using mint = modint998244353;
constexpr int IINF = 1001001001;
constexpr ll INF = 9e18;

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

// ここから
class RollbackUnionFind {
    vector<ll> parent;
    stack<pair<int, int>> history;
    int inner_snap;


public:
    RollbackUnionFind(ll n_ = 1): inner_snap(0){ parent.assign(n_, -1); }

    inline int find(int x){
        // 経路圧縮を行わない
        return (parent[x] < 0? x:find(parent[x]));
    }

    inline bool same(int x, int y){
        return find(x) == find(y);
    }

    inline bool unite(int x, int y){
        x = find(x), y = find(y);
        history.emplace(x, parent[x]);
        history.emplace(y, parent[y]);
        if(x == y) return false;
        if(parent[x] > parent[y]) swap(x, y);
        parent[x] += parent[y];
        parent[y] = x;
        return true;
    }

    // rollback処理（stackの上2つを使って戻す）
    inline void undo(){
        parent[history.top().first] = history.top().second;
        history.pop();
        parent[history.top().first] = history.top().second;
        history.pop();
    }

    void snapshot() { inner_snap = int(history.size() >> 1); }

    int get_state() { return int(history.size() >> 1); }

    void rollback(int state = -1) {
        if (state == -1) state = inner_snap;
        state <<= 1;
        assert(state <= (int)history.size());
        while (state < (int)history.size()) undo();
    }

    inline int size(int x){
        return (-parent[find(x)]);
    }

    inline int operator[](int x){
        return find(x);
    }
};

int main(){
    while(true){
        int n, m; cin >> n >> m;
        if(n == 0 && m == 0) break;

        vector<vector<pair<int, int>>> edge(100005);
        vector<vector<bool>> connect(100005);
        vector<vector<pair<int, int>>> g(n);
        rep(i, 0, m){
            int a, b, s; cin >> a >> b >> s;
            a--, b--;
            edge[s].push_back({a, b});
            g[a].push_back({b, s});
            g[b].push_back({a, s});
        }
        RollbackUnionFind uf(n);
        rrep(i, 100000, 1){
            for(auto [u, v]: edge[i]){
                connect[i].push_back(!uf.same(u, v));
                uf.unite(u, v);
            }
            reverse(edge[i].begin(), edge[i].end());
            reverse(connect[i].begin(), connect[i].end());
        }
        set<pair<int, int>> c;
        c.insert({uf.size(0), uf[0]});
        vector<bool> ng(n, false);
        rep(i, 1, 100001){
            rep(j, 0, edge[i].size()){
                auto [u, v] = edge[i][j];
                // cout << u << ' ' << v << ' ' << (connect[i][j] ? "connect": "no") << endl;
                int sz = uf.size(u), root = uf[u];
                uf.undo();
                if(!connect[i][j]) continue;
                int pu = uf[u], pv = uf[v];
                if(!ng[u] && !ng[v] && pu != pv){
                    c.erase(c.find({sz, root}));
                    c.insert({uf.size(u), pu});
                    c.insert({uf.size(v), pv});
                }
            }

            int mx = (*c.rbegin()).first;
            if(mx == 1) break;
            while((*c.begin()).first < mx){
                auto [s, r] = (*c.begin());
                c.erase(c.begin());
                queue<int> que;
                que.push(r);
                ng[r] = 1;
                while(!que.empty()){
                    int q = que.front(); que.pop();
                    for(auto [nq, cost]: g[q]){
                        if(cost <= i) continue;
                        if(ng[nq]) continue;
                        ng[nq] = 1;
                        que.push(nq);
                    }
                }
            }
        }

        vector<int> ans;
        rep(i, 0, n){
            if(ng[i]) continue;
            ans.push_back(i+1);
        }
        cout << ans[0];
        rep(i, 1, ans.size()){
            cout << ' ' << ans[i];
        }
        cout << endl;

    }

    return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 23644
final_rank: 17

code_snippet: #include <bits/stdc++.h>
// #include <atcoder/all>
using namespace std;
// using namespace atcoder;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define rrep(i, a, n) for(int i = a; i >= n; i--)
#define inr(l, x, r) (l <= x && x < r)
#define ll long long
#define ld long double

// using mint = modint1000000007;
// using mint = modint998244353;
constexpr int IINF = 1001001001;
constexpr ll INF = 9e18;

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

// ここから
class RollbackUnionFind {
    vector<ll> parent;
    stack<pair<int, int>> history;
    int inner_snap;


public:
    RollbackUnionFind(ll n_ = 1): inner_snap(0){ parent.assign(n_, -1); }

    inline int find(int x){
        // 経路圧縮を行わない
        return (parent[x] < 0? x:find(parent[x]));
    }

    inline bool same(int x, int y){
        return find(x) == find(y);
    }

    inline bool unite(int x, int y){
        x = find(x), y = find(y);
        history.emplace(x, parent[x]);
        history.emplace(y, parent[y]);
        if(x == y) return false;
        if(parent[x] > parent[y]) swap(x, y);
        parent[x] += parent[y];
        parent[y] = x;
        return true;
    }

    // rollback処理（stackの上2つを使って戻す）
    inline void undo(){
        parent[history.top().first] = history.top().second;
        history.pop();
        parent[history.top().first] = history.top().second;
        history.pop();
    }

    void snapshot() { inner_snap = int(history.size() >> 1); }

    int get_state() { return int(history.size() >> 1); }

    void rollback(int state = -1) {
        if (state == -1) state = inner_snap;
        state <<= 1;
        assert(state <= (int)history.size());
        while (state < (int)history.size()) undo();
    }

    inline int size(int x){
        return (-parent[find(x)]);
    }

    inline int operator[](int x){
        return find(x);
    }
};

int main(){
    while(true){
        int n, m; cin >> n >> m;
        if(n == 0 && m == 0) break;

        vector<vector<pair<int, int>>> edge(100005);
        vector<vector<bool>> connect(100005);
        vector<vector<pair<int, int>>> g(n);
        rep(i, 0, m){
            int a, b, s; cin >> a >> b >> s;
            a--, b--;
            edge[s].push_back({a, b});
            g[a].push_back({b, s});
            g[b].push_back({a, s});
        }
        RollbackUnionFind uf(n);
        rrep(i, 100000, 1){
            for(auto [u, v]: edge[i]){
                connect[i].push_back(!uf.same(u, v));
                uf.unite(u, v);
            }
            reverse(edge[i].begin(), edge[i].end());
            reverse(connect[i].begin(), connect[i].end());
        }
        set<pair<int, int>> c;
        c.insert({uf.size(0), uf[0]});
        vector<bool> ng(n, false);
        rep(i, 1, 100001){
            rep(j, 0, edge[i].size()){
                auto [u, v] = edge[i][j];
                // cout << u << ' ' << v << ' ' << (connect[i][j] ? "connect": "no") << endl;
                int sz = uf.size(u), root = uf[u];
                uf.undo();
                if(!connect[i][j]) continue;
                // cout << u << ' ' << v << ' ' << uf[u] << ' ' << uf[v] << endl;
                if(!ng[u] && !ng[v] && uf[u] != uf[v]){
                    c.erase(c.find({sz, root}));
                    c.insert({uf.size(u), uf[u]});
                    c.insert({uf.size(v), uf[v]});
                }
            }

            int mx = (*c.rbegin()).first;
            if(mx == 1) break;
            while((*c.begin()).first < mx){
                auto [s, r] = (*c.begin());
                c.erase(c.begin());
                queue<int> que;
                que.push(r);
                ng[r] = 1;
                while(!que.empty()){
                    int q = que.front(); que.pop();
                    for(auto [nq, cost]: g[q]){
                        if(cost <= i) continue;
                        if(ng[nq]) continue;
                        ng[nq] = 1;
                        que.push(nq);
                    }
                }
            }
        }

        vector<int> ans;
        rep(i, 0, n){
            if(ng[i]) continue;
            ans.push_back(i+1);
        }
        cout << ans[0];
        rep(i, 1, ans.size()){
            cout << ' ' << ans[i];
        }
        cout << endl;

    }

    return 0;
}
accuracy: 1
time_ms: 350
memory_kb: 23880
final_rank: 18

code_snippet: #include <bits/stdc++.h>
// #include <atcoder/all>
using namespace std;
// using namespace atcoder;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define rrep(i, a, n) for(int i = a; i >= n; i--)
#define inr(l, x, r) (l <= x && x < r)
#define ll long long
#define ld long double

// using mint = modint1000000007;
// using mint = modint998244353;
constexpr int IINF = 1001001001;
constexpr ll INF = 9e18;

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

// ここから
class RollbackUnionFind {
    vector<ll> parent;
    stack<pair<int, int>> history;
    int inner_snap;


public:
    RollbackUnionFind(ll n_ = 1): inner_snap(0){ parent.assign(n_, -1); }

    inline int find(int x){
        // 経路圧縮を行わない
        return (parent[x] < 0? x:find(parent[x]));
    }

    inline bool same(int x, int y){
        return find(x) == find(y);
    }

    inline bool unite(int x, int y){
        x = find(x), y = find(y);
        history.emplace(x, parent[x]);
        history.emplace(y, parent[y]);
        if(x == y) return false;
        if(parent[x] > parent[y]) swap(x, y);
        parent[x] += parent[y];
        parent[y] = x;
        return true;
    }

    // rollback処理（stackの上2つを使って戻す）
    inline void undo(){
        parent[history.top().first] = history.top().second;
        history.pop();
        parent[history.top().first] = history.top().second;
        history.pop();
    }

    void snapshot() { inner_snap = int(history.size() >> 1); }

    int get_state() { return int(history.size() >> 1); }

    void rollback(int state = -1) {
        if (state == -1) state = inner_snap;
        state <<= 1;
        assert(state <= (int)history.size());
        while (state < (int)history.size()) undo();
    }

    inline int size(int x){
        return (-parent[find(x)]);
    }

    inline int operator[](int x){
        return find(x);
    }
};

int main(){
    while(true){
        int n, m; cin >> n >> m;
        if(n == 0 && m == 0) break;

        vector<vector<pair<int, int>>> edge(100005);
        vector<vector<bool>> connect(100005);
        vector<vector<pair<int, int>>> g(n);
        rep(i, 0, m){
            int a, b, s; cin >> a >> b >> s;
            a--, b--;
            edge[s].push_back({a, b});
            g[a].push_back({b, s});
            g[b].push_back({a, s});
        }
        RollbackUnionFind uf(n);
        rrep(i, 100000, 1){
            for(auto [u, v]: edge[i]){
                connect[i].push_back(!uf.same(u, v));
                uf.unite(u, v);
            }
            reverse(edge[i].begin(), edge[i].end());
            reverse(connect[i].begin(), connect[i].end());
        }
        set<pair<int, int>> c;
        c.insert({uf.size(0), uf[0]});
        vector<bool> ng(n, false);
        rep(i, 1, 100001){
            rep(j, 0, edge[i].size()){
                auto [u, v] = edge[i][j];
                // cout << u << ' ' << v << ' ' << (connect[i][j] ? "connect": "no") << endl;
                int sz = uf.size(u), root = uf[u];
                uf.undo();
                if(!connect[i][j]) continue;
                // cout << u << ' ' << v << ' ' << uf[u] << ' ' << uf[v] << endl;
                if(!ng[u] && !ng[v] && uf[u] != uf[v]){
                    c.erase(c.find({sz, root}));
                    c.insert({uf.size(u), uf[u]});
                    c.insert({uf.size(v), uf[v]});
                }
            }

            int mx = (*c.rbegin()).first;
            if(mx == 1) break;
            set<pair<int, int>> c_ = c;
            for(auto [s, r]: c){
                if(s == mx) break;
                queue<int> que;
                que.push(r);
                ng[r] = 1;
                while(!que.empty()){
                    int q = que.front(); que.pop();
                    for(auto [nq, cost]: g[q]){
                        if(cost <= i) continue;
                        if(ng[nq]) continue;
                        ng[nq] = 1;
                        que.push(nq);
                    }
                }
                c_.erase(c_.begin());
            }
            swap(c_, c);
        }

        vector<int> ans;
        rep(i, 0, n){
            if(ng[i]) continue;
            ans.push_back(i+1);
        }
        cout << ans[0];
        rep(i, 1, ans.size()){
            cout << ' ' << ans[i];
        }
        cout << endl;

    }

    return 0;
}
accuracy: 1
time_ms: 1250
memory_kb: 23808
final_rank: 20