CF1368E Ski Accidents

读懂题是第一要素。

考虑把点集分割为:\(A,B,C\)

首先把所有入度为\(0\)的点加入\(A\)
然后对所有入边只来自\(A\)的点加入\(B\)
然后对所有入边只来自\(B\)的点加入\(C\)

剩下的全部加入\(C\)

此时:

A:只有入度为0的点,或者全部入边全来自C
B:只有来自A的入度
C:至少有来自B的入度

那么这要我们删掉C,即可保证没有三点是联通的。

由于每个点只有两个出度,所以我们可以证明,\(|C| \leq \frac{4}{7}n\)

#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
#define ll long long 
#define N 200005

ll n,m;
ll t;
std::vector<ll>to[N];		
std::vector<int>ans;

int main(){
	scanf("%lld",&t);
	while(t -- ){
	ans.clear();
	scanf("%lld%lld",&n,&m);
	for(int i = 1;i <= n;++i)
	to[i].clear();
	for(int i = 1;i <= m;++i){
		ll x,y;
		scanf("%lld%lld",&x,&y);
		to[y].push_back(x);
	}
	std::vector<int>color(n);	
	for(int i = 1;i <= n;++i){
		for(int j = 0;j < to[i].size();++j){
			int u = to[i][j];
			if(color[u] == 1)
			color[i] = 2;
			if(color[i] != 2 && color[u] == 0)
			color[i] = 1;
		}
	}
	for(int i = 1;i <= n;++i)
	if(color[i] == 2)
	ans.push_back(i);
	std::cout<<ans.size()<<std::endl;
	for(int i = 0;i < ans.size();++i)
	std::cout<<ans[i]<<" ";	
	puts("");	
	}
}
posted @ 2021-08-23 13:48  fhq_treap  阅读(35)  评论(0编辑  收藏  举报