#拓撲排序#洛谷 5157 [USACO18DEC]The Cow Gathering P
阿新 • • 發佈:2021-12-21
拓撲排序
題目
給出一棵樹和一些限制關係 \((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; }