题解 P2999【[USACO10NOV]Chocolate Milk S】
这题应该使用拓扑排序。
思路
给定每个挤奶器牛奶流量 \(1\), 并用数组 $milk $ 记录每个节点可以流经来自多少个不同挤奶器的牛奶,子接口可以流经来自父接口的所有牛奶。
进行拓扑排序,若某节点的流量为挤奶器的数量,则该节点可以放置巧克力混合器。
对于牛奶来说,最多只有一种方式从一个接口流到另一个接口。
因此不会有牛奶分流后再重新聚集到一点,即除了入度为 \(0\) 的节点外,一个出度大于 \(1\) 的节点的子节点都不能放置巧克力混合器。
其余的细节参考代码及注释。
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
vector<int>G[N];
queue<int>q;
int ind[N],f[N],milk[N];
bool ism[N];
int n,m,sum;
void topo()
{
for(int i=1;i<=n;i++)
{
if(!ind[i])
{
q.push(i);
ism[i] = true; //标记挤奶器
milk[i] = 1; //记录每个接口可以流经来自多少个挤奶器的牛奶
sum++; //一共有多少个挤奶器
}
}
while(!q.empty())
{
int u = q.front();
q.pop();
if(G[u].size()>1) //牛奶不会在分流后聚集到一点
{
continue;
}
for(int i=0;i<G[u].size();i++)
{
int v = G[u][i];
ind[v]--;
milk[v]+=milk[u]; //上一个接口的牛奶可以流向该接口
if(!ind[v]) q.push(v);
}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++) //一共有n-1条管道
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
ind[v]++; //记录出度
}
topo();
for(int i=1;i<=n;i++)
{
if(!ism[i]&&milk[i]==sum) //如果不是挤奶器,并且来自所有挤奶器的牛奶都可以流经该接口
{
printf("%d\n",i);
}
}
return 0;
}

浙公网安备 33010602011771号