#拓扑排序#洛谷 5157 [USACO18DEC]The Cow Gathering P

题目

给出一棵树和一些限制关系 \((a_i,b_i)\)

一种合法的删点序列当且仅当删除一个点之后树的大小不超过 1 或不存在孤立点,

并且 \(a_i\) 要比 \(b_i\) 先删除,问 \(\forall x\in [1,n]\),是否可能为合法删点序列的末项


分析

考虑到限制就是 \(a_i\) 不包含 \(b_i\) 的那些子树包括 \(a_i\) 本身不可能为末项。

并且如果有一个点可能为末项,那么与其不通过被限制的点相连的也可以成为末项。

所以只要找到一个合法的末项即可,如果没有限制随便挑一个就行了。

考虑把限制看成单向边,每次把所谓的叶子加进队列,

如果叶子发现度数为 0 说明无论限制还是树均被满足,那么它就可以成为末项


代码

#include <cstdio>
#include <cctype>
#include <vector>
using namespace std;
const int N=100011;
struct node{int y,next;}e[N<<1]; vector<int>G[N];
int as[N],ans[N],q[N],head=1,tail,deg[N],n,et=1,m,rt;
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
int Topsort(){
	for (int i=1;i<=n;++i)
	    if (deg[i]==1) q[++tail]=i;
	while (head<=tail){
		int x=q[head++];
		if (deg[x]<1) return x;
		for (int i=as[x];i;i=e[i].next)
		    if (--deg[e[i].y]==1) q[++tail]=e[i].y;
		for (int i=0;i<(int)G[x].size();++i)
		    if (--deg[G[x][i]]==1) q[++tail]=G[x][i];
	}
	return tail==n;
}
void dfs(int x){
	ans[x]=1;
	for (int i=as[x];i;i=e[i].next)
	    if (!ans[e[i].y]) dfs(e[i].y);
}
int main(){
	n=iut(),m=iut();
	for (int i=1;i<n;++i){
		int x=iut(),y=iut();
		e[++et]=(node){y,as[x]},as[x]=et,++deg[x];
		e[++et]=(node){x,as[y]},as[y]=et,++deg[y];
	}
	for (int i=1;i<=m;++i){
		int x=iut(),y=iut();
		G[x].push_back(y);
		ans[x]=-1,++deg[y];
	}
	rt=Topsort();
	if (!rt){
		for (int i=1;i<=n;++i)
		    putchar(48),putchar(10);
		return 0;
	}
	dfs(rt);
	for (int i=1;i<=n;++i,putchar(10))
	if (ans[i]==1) putchar(49);
        else putchar(48);
	return 0;
}
posted @ 2021-12-21 11:33  lemondinosaur  阅读(28)  评论(0编辑  收藏  举报