CodeForces-160D.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. #include <algorithm>
  2. #include <functional>
  3. #include <iostream>
  4. #include <numeric>
  5. #include <string>
  6. #include <utility>
  7. #include <vector>
  8. using namespace std;
  9. struct DSU {
  10. vector<int> p, s;
  11. explicit DSU(int n) : p(n), s(n, 1) { iota(p.begin(), p.end(), 0); }
  12. int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }
  13. void unite(int a, int b) {
  14. a = find(a); b = find(b); if (a == b) return;
  15. if (s[a] < s[b]) swap(a, b); p[b] = a; s[a] += s[b];
  16. }
  17. };
  18. struct Edge { int u, v, w, id; };
  19. int main() {
  20. ios::sync_with_stdio(false);
  21. cin.tie(nullptr);
  22. int n, m; cin >> n >> m;
  23. vector<Edge> edges(m);
  24. for (int i = 0; i < m; ++i) {
  25. cin >> edges[i].u >> edges[i].v >> edges[i].w;
  26. --edges[i].u; --edges[i].v; edges[i].id = i;
  27. }
  28. sort(edges.begin(), edges.end(), [](const Edge &a, const Edge &b) { return a.w < b.w; });
  29. vector<string> answer(m, "none"); DSU dsu(n);
  30. for (int left = 0; left < m; ) {
  31. int right = left;
  32. while (right < m && edges[right].w == edges[left].w) ++right;
  33. vector<int> candidate, roots;
  34. for (int i = left; i < right; ++i) {
  35. int a = dsu.find(edges[i].u), b = dsu.find(edges[i].v);
  36. if (a != b) {
  37. candidate.push_back(i); roots.push_back(a); roots.push_back(b);
  38. answer[edges[i].id] = "at least one";
  39. }
  40. }
  41. sort(roots.begin(), roots.end()); roots.erase(unique(roots.begin(), roots.end()), roots.end());
  42. vector<vector<pair<int, int>>> graph(roots.size());
  43. for (int index : candidate) {
  44. int a = int(lower_bound(roots.begin(), roots.end(), dsu.find(edges[index].u)) - roots.begin());
  45. int b = int(lower_bound(roots.begin(), roots.end(), dsu.find(edges[index].v)) - roots.begin());
  46. graph[a].push_back({b, edges[index].id}); graph[b].push_back({a, edges[index].id});
  47. }
  48. vector<int> tin(roots.size(), -1), low(roots.size()); int timer = 0;
  49. function<void(int, int)> dfs = [&](int u, int parent_edge) {
  50. tin[u] = low[u] = timer++;
  51. for (auto [v, id] : graph[u]) {
  52. if (id == parent_edge) continue;
  53. if (tin[v] == -1) {
  54. dfs(v, id); low[u] = min(low[u], low[v]);
  55. if (low[v] > tin[u]) answer[id] = "any";
  56. } else low[u] = min(low[u], tin[v]);
  57. }
  58. };
  59. for (int v = 0; v < static_cast<int>(roots.size()); ++v) if (tin[v] == -1) dfs(v, -1);
  60. for (int i = left; i < right; ++i) dsu.unite(edges[i].u, edges[i].v);
  61. left = right;
  62. }
  63. for (const string &s : answer) cout << s << '\n';
  64. }