problem
solution
这个 4 7 n \frac 47n 74n 的限制,提示这存在一个特定构造方案,由 7 7 7 我们联想到 1 + 2 + 4 = 7 1+2+4=7 1+2+4=7。
暗示把顶点分为三类 A , B , C A,B,C A,B,C,满足 ∣ C ∣ ≤ 2 ∣ B ∣ ≤ 4 ∣ A ∣ |C|\le 2|B|\le 4|A| ∣C∣≤2∣B∣≤4∣A∣。
此时 C C C 组的元素数目一定 ≤ 4 7 n \le \frac{4}{7}n ≤74n。
- 构造方式:把所有入度为 0 0 0 的点都放入 A A A,把至少有一条入边来自 A A A ,但没有来自 B B B 的入边的点放入 B B B。然后,把至少有一条入边来自 B B B 的入边的点放入 C C C。剩下的点(所有入边都来 C C C )放入 A A A。
此时,各类包含的顶点要求为:
- A : A: A: 入度为 0 0 0;所有入边都来自 C C C。
- B : B: B: 至少有一条入边来自 A A A,但没有来自 B B B 的入边。
- C : C: C: 至少有一条入边来自 B B B。
不难发现,三类形成了一个有效的集合划分。
且因为每个点的出度都不超过 2 2 2,即 A A A 的出边至多有 2 ∣ A ∣ 2|A| 2∣A∣ 条,所以 2 ∣ A ∣ ≥ ∣ B ∣ 2|A|\ge |B| 2∣A∣≥∣B∣, 2 ∣ B ∣ ≥ ∣ C ∣ 2|B|\ge |C| 2∣B∣≥∣C∣ 同理。
此时将 C C C 类点尽数删除。
由于 A , B A,B A,B 都没有来自 B B B 的入边,而 A A A 内部点之间也不存在边,所以一定不存在长度超过 1 1 1 的路径。
有向无环图,所以可以在 O ( n ) O(n) O(n) 的时间内完成求解。
code
#include <bits/stdc++.h>
using namespace std;
#define maxn 200005
vector < int > G[maxn], ans;
int T, n, m;
int col[maxn];
int main() {
scanf( "%d", &T );
while( T -- ) {
scanf( "%d %d", &n, &m );
for( int i = 1;i <= n;i ++ ) G[i].clear(), col[i] = 0;
for( int i = 1, u, v;i <= m;i ++ ) {
scanf( "%d %d", &u, &v );
G[v].push_back( u );
}
for( int v = 1;v <= n;v ++ )
for( int u : G[v] ) {
if( col[u] == 1 )
col[v] = 2;
if( col[v] ^ 2 and col[u] == 0 )
col[v] = 1;
}
ans.clear();
for( int i = 1;i <= n;i ++ )
if( col[i] == 2 ) ans.push_back( i );
printf( "%d\n", ans.size() );
for( int i : ans ) printf( "%d ", i );
puts("");
}
return 0;
}