思路

这题需要使用拓扑排序。

如何使用呢?我们看这张图。

如图,112233 三个点是挤奶器,假设它们的流量为 11,其他每个点的流量为它所有父节点流量的和。

为什么 8899 点没有标记呢?因为 77 点的出度大于 11,所以 88 点和 99 点都不可能成为安装的点。(划重点!!!)

所以,我们可以用拓扑排序递推每个点的流量,流量正好等于挤奶器个数且不为挤奶器的点才可以安装!

代码

#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; // 判断并输出
	}
}