前置知识 --> 拓扑排序
这道题为什么要用拓扑排序呢?因据题意,每一个点奶的流量都有先后顺序,且顺序不得改动。
重点在于本题入度,出度,队列等的运用。
思路
挤奶器:入度为 0,且可以最早入队列(因为它不受先后顺序的限制);
混合器:混合器要放在每一个奶流都会经过的点,则该点的奶流量 = 总奶流量;
while 入队出队操作:当队头的出度为 1 时,可以将之前记录下来的他的“子节点”操作之后,入队;
答案统计:在将挤奶器入队时,统计总奶量,每一个挤奶器的奶量为 1, 并用 tot 统计,最后比较该点的奶流量是否与总奶量相等,若相等,则记录。
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int n;
int to[maxn], ans[maxn];
int rd[maxn], cd[maxn];
int liu[maxn], ji[maxn];//挤奶器
int tot;
queue <int> q;
int main()
{
scanf ("%d", &n);
for (int i = 1; i < n; i++)
{
int a, b;
scanf ("%d %d", &a, &b);
to[a] = b;
cd[a]++;
rd[b]++;
}
for (int i = 1; i <= n; i++)//寻找挤奶器
{
if (!rd[i])
{
liu[i] = 1;
tot += 1;
q.push (i);
ji[i] = 1;
}
}
while (!q.empty())
{
int x = q.front ();
q.pop ();
if (cd[x] > 1) continue;
//拓扑
liu[to[x]] += liu[x];
rd[to[x]] --;
if (!rd[to[x]]) q.push (to[x]);
}
int tmp = 1;
for (int i = 1; i <= n; i++)
{
if (ji[i]) continue;//挤奶器
if (tot == liu[i])
{
ans[tmp] = i;
tmp ++;
}
}
for (int i = 1; i < tmp; i++) printf ("%d\n", ans[i]);
return 0;
}