CF1019C
题意
给 \(n\) 个点 \(m\) 条边有向图。
问求出任意一个点集 \(S\) 满足 \(\forall\ u,\ v\ \in\ S,\ d(u,\ v)\ >\ 1\ or\ u\ =\ v\) 且 \(\forall\ u\ \notin\ S,\ \exists\ v\ \in\ S,\ d(v,\ u)\ \leq\ 2\)。
\(1\ \leq\ n,\ m\ \leq\ 10^6\)
做法
考虑归纳法,取出点 \(u\) 以及 \(u\) 连向的所有点,将这些点删去后的答案设为 \(T\)。如果 \(T\) 中有点 \(v\) 使得 \(v,\ u\) 有边相连,则无需选择 \(u\) 否则选 \(u\)。
时间复杂度 \(O(n\ +\ m)\)
代码
#include <bits/stdc++.h>
#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif
#ifdef __WIN32
#define LLFORMAT "I64"
#define Rand() ((rand() << 15) + rand())
#else
#define LLFORMAT "ll"
#define Rand() (rand())
#endif
using namespace std;
const int maxn = 1e6 + 10;
template<int input_SZ, int output_SZ> struct IO {
char s[input_SZ], t[output_SZ], *a, *b;
IO() { fread(s, 1, input_SZ, stdin); a = s; b = t; }
~IO() { fwrite(t, 1, b - t, stdout); }
char nextchar(char c) {
return *a++;
}
int nextint() {
while(*a != '-' && (*a < '0' || *a > '9')) ++a;
bool flag = 0; int x = 0;
if(*a == '-') ++a, flag = 1;
while(*a >= '0' && *a <= '9') x = x * 10 + *a++ - '0';
if(flag) x = -x;
return x;
}
long long nextll() {
while(*a != '-' && (*a < '0' || *a > '9')) ++a;
bool flag = 0; long long x = 0;
if(*a == '-') ++a, flag = 1;
while(*a >= '0' && *a <= '9') x = x * 10 + *a++ - '0';
if(flag) x = -x;
return x;
}
void outchar(char c) {
*b++ = c;
if(b - t > output_SZ - 25) { fwrite(t, 1, b - t, stdout); b = t; }
return;
}
template<typename T> void outnum(T x) {
if(!x) { *b++ = '0'; return; }
if(x < 0) *b++ = '-', x = -x;
static char s[20], *a;
a = s;
while(x) {
T y = x / 10;
*a++ = x - y * 10 + '0';
x = y;
}
while(a != s) *b++ = *--a;
if(b - t > output_SZ - 25) { fwrite(t, 1, b - t, stdout); b = t; }
return;
}
template<typename T> void outnum(T x, char c) {
return outnum(x), outchar(c);
}
};
IO<(1 << 24) | 10, (1 << 23) | 10> io;
int n, m, f[maxn], stk[maxn], top;
vector<int> g[maxn], ans;
void upd(int u) { for (int v: g[u]) f[v] = 2; }
int main() {
n = io.nextint(); m = io.nextint();
for (int i = 0; i < m; ++i) {
int u = io.nextint(), v = io.nextint();
g[u].push_back(v);
}
for (int u = 1; u <= n; ++u) {
if(!f[u]) {
stk[top++] = u;
f[u] = 1;
for (int v: g[u]) f[v] = 1;
}
}
int u = stk[--top]; f[u] = 0; upd(u); ans.push_back(u);
while(top--) {
int u = stk[top];
if(f[u] == 1) f[u] = 0, upd(u), ans.push_back(u);
}
io.outnum(ans.size(), '\n');
for (int u: ans) io.outnum(u, ' ');
return 0;
}