#include <algorithm>
#include <cstdio>
#include <stack>
#include <vector>
using namespace std;
class FindUnion {
public:
FindUnion(const int n) : parent_(n, -1) {}
int Find(int i) {
int j = i;
while (parent_[j] >= 0) j = parent_[j];
while (parent_[i] >= 0) {
int k = parent_[i];
parent_[i] = j;
i = k;
}
return j;
}
int Size(int i) {
i = Find(i);
return -parent_[i];
}
void Union(int i, int j) {
i = Find(i);
j = Find(j);
if (i == j) return;
if (parent_[i] < parent_[j]) {
parent_[i] += parent_[j];
parent_[j] = i;
} else {
parent_[j] += parent_[i];
parent_[i] = j;
}
}
private:
vector<int> parent_;
};
stack<int> s;
vector<bool> deleted;
void Enqueue(const int i) {
if (deleted[i]) return;
deleted[i] = true;
s.push(i);
}
int main() {
int n;
int m;
int d;
scanf("%d%d%d", &n, &m, &d);
deleted.resize(n, false);
vector<int> degree(n, 0);
vector<pair<int, int> > edges;
while (m--) {
int a;
int b;
scanf("%d%d", &a, &b);
++degree[--a];
++degree[--b];
edges.push_back(make_pair(a, b));
edges.push_back(make_pair(b, a));
}
sort(edges.begin(), edges.end());
vector<int> offsets;
{
int i = 0;
while (i < edges.size()) {
while (edges[i].first >= offsets.size()) offsets.push_back(i);
++i;
}
while (offsets.size() <= n) offsets.push_back(i);
}
for (int i = 0; i < n; ++i) if (degree[i] < d) Enqueue(i);
while (!s.empty()) {
const int i = s.top();
s.pop();
for (int j = offsets[i]; j < offsets[i + 1]; ++j)
if (--degree[edges[j].second] < d) Enqueue(edges[j].second);
}
FindUnion f(n);
for (int i = 0; i < n; ++i) if (!deleted[i]) {
for (int j = offsets[i]; j < offsets[i + 1]; ++j)
if (!deleted[edges[j].second]) f.Union(i, edges[j].second);
}
int best = -1;
for (int i = 0; i < n; ++i) if (!deleted[i])
if (best == -1 || f.Size(i) > f.Size(best)) best = i;
if (best == -1) {
printf("NIE\n");
} else {
printf("%d\n%d", f.Size(best), best + 1);
for (int i = 0; i < n; ++i) if (i != best) if (f.Find(i) == f.Find(best))
printf(" %d", i + 1);
printf("\n");
}
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | #include <algorithm> #include <cstdio> #include <stack> #include <vector> using namespace std; class FindUnion { public: FindUnion(const int n) : parent_(n, -1) {} int Find(int i) { int j = i; while (parent_[j] >= 0) j = parent_[j]; while (parent_[i] >= 0) { int k = parent_[i]; parent_[i] = j; i = k; } return j; } int Size(int i) { i = Find(i); return -parent_[i]; } void Union(int i, int j) { i = Find(i); j = Find(j); if (i == j) return; if (parent_[i] < parent_[j]) { parent_[i] += parent_[j]; parent_[j] = i; } else { parent_[j] += parent_[i]; parent_[i] = j; } } private: vector<int> parent_; }; stack<int> s; vector<bool> deleted; void Enqueue(const int i) { if (deleted[i]) return; deleted[i] = true; s.push(i); } int main() { int n; int m; int d; scanf("%d%d%d", &n, &m, &d); deleted.resize(n, false); vector<int> degree(n, 0); vector<pair<int, int> > edges; while (m--) { int a; int b; scanf("%d%d", &a, &b); ++degree[--a]; ++degree[--b]; edges.push_back(make_pair(a, b)); edges.push_back(make_pair(b, a)); } sort(edges.begin(), edges.end()); vector<int> offsets; { int i = 0; while (i < edges.size()) { while (edges[i].first >= offsets.size()) offsets.push_back(i); ++i; } while (offsets.size() <= n) offsets.push_back(i); } for (int i = 0; i < n; ++i) if (degree[i] < d) Enqueue(i); while (!s.empty()) { const int i = s.top(); s.pop(); for (int j = offsets[i]; j < offsets[i + 1]; ++j) if (--degree[edges[j].second] < d) Enqueue(edges[j].second); } FindUnion f(n); for (int i = 0; i < n; ++i) if (!deleted[i]) { for (int j = offsets[i]; j < offsets[i + 1]; ++j) if (!deleted[edges[j].second]) f.Union(i, edges[j].second); } int best = -1; for (int i = 0; i < n; ++i) if (!deleted[i]) if (best == -1 || f.Size(i) > f.Size(best)) best = i; if (best == -1) { printf("NIE\n"); } else { printf("%d\n%d", f.Size(best), best + 1); for (int i = 0; i < n; ++i) if (i != best) if (f.Find(i) == f.Find(best)) printf(" %d", i + 1); printf("\n"); } return 0; } |
English