思路
这题需要使用拓扑排序。
如何使用呢?我们看这张图。

如图,、、 三个点是挤奶器,假设它们的流量为 ,其他每个点的流量为它所有父节点流量的和。
为什么 、 点没有标记呢?因为 点的出度大于 ,所以 点和 点都不可能成为安装的点。(划重点!!!)
所以,我们可以用拓扑排序递推每个点的流量,流量正好等于挤奶器个数且不为挤奶器的点才可以安装!
代码
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
int d, rd[100001], s[100001], n, u, v; // rd表示入度,s表示流量,d为挤奶器的数量
vector<int> edge[100001];
bool ccc[100001]; // 是否为挤奶器
int main(){
cin >> n;
for (int i = 1;i < n;i ++){
cin >> u >> v;
edge[u].push_back(v);
rd[v] ++; // 统计入度
}
queue<int> q;
for (int i = 1;i <= n;i ++){
if (rd[i] == 0) q.push(i), s[i] = ccc[i] = 1, d ++; // 如果为挤奶器
}
while (q.size()){ // 拓扑排序
int f = q.front();
q.pop();
if (edge[f].size() == 1){ // 如果出度大于1,下一个点就不能混合所有的牛奶,所以只有出度等于1,才能进入下一个点。
v = edge[f][0];
rd[v] --; // 减少出度
s[v] += s[f]; // 统计流量
if (rd[v] == 0) q.push(v); // 压进新的点
}
}
for (int i = 1;i <= n;i ++){
if (d == s[i] && !ccc[i]) cout << i << endl; // 判断并输出
}
}