#拓扑排序#洛谷 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;
}