using namespace std;
const int N=100005;
int h[N],to[N],ne[N],cnt=1;//链式前向星
int inde[N],outde[N],q[N],ans[N];//入度,出度,队列模拟,记录到每个点时前面点的贡献
int head=0,tail=0;//队列首位
bool ismilk[N];
void add(int a,int b){
to[cnt]=b;
ne[cnt]=h[a];
h[a]=cnt++;
inde[b]++;
outde[a]++;
}
void solve(){
while(head<tail){
int t=q[head++];
if(outde[t]>1)continue;
for(int i=h[t];i;i=ne[i]){
int temp=to[i];
ans[temp]=ans[temp]+ans[t];
inde[temp]--;
if(inde[temp]==0)q[tail++]=temp;
}
}
}
int main(){
int n,ai,bi,incnt=0;
cin>>n;
memset(h,0,sizeof(h));
memset(ismilk,false,sizeof(ismilk));
for(int i=1;i<n;i++){
cin>>ai>>bi;
add(ai,bi);
}
for(int i=1;i<=n;i++){
if(!inde[i]){
incnt++;
q[tail++]=i;
ans[i]=1;
ismilk[i]=true;
}
}
solve();
for(int i=1;i<=n;i++){
if(ans[i]==incnt&&!ismilk[i]){
cout<<i<<"\n";
}
}
}
本题目关键在于以下几点: 1.有向无环图 2.牛奶流向是从一个点到另一个点,有且只有一种路径,所以只要某节点分叉了,那么之后子节点一定不可能是混合器所在位置 3.混合器不能放在挤奶器(入度为零的点)
所以我们就有大致思路,对于抛去挤奶器的点,只要该点被所有挤奶器流过,那么就可以输出作为答案,本题牛奶都能流到奶槽里所以不用额外判断,是否能到达奶槽。挤奶器是源点,入度为零,所以可以用拓扑排序,通过一个ans数组来记录到当前点的累计贡献也就是有几个挤奶器的奶流过,最后判断ans数组里面是否有贡献点等于挤奶器数量,且不与挤奶器重复的点,从小到大输出即可。
链式前向星存图,遍历图,找到入度为0的点,打上标记,记录数量,数组模拟队列实现拓扑排序,这里有个关键剪枝对于出度大于1的点也就是分叉节点,其后的的点一定不可能是答案所以跳过;

京公网安备 11010502036488号