Chocolate Milk(洛谷P2999)
拓扑排序
关于拓扑排序,这里不叙述太多,可参考本人CSDN。
值得注意的是,这不是一棵树吗?
FJ 发现对于牛奶来说有一种最多的方式从一个接口流到另一个接口。并且由于 FJ 是一个高效率的人,他需要确保每一个管道都有牛奶经过,也就是说,没有多余的管道。
所以,对于牛奶来说,最多只有一种方式从一个接口流到另一个接口。则不会有牛奶分开又聚到一起。
故有一个性质:除非节点的入度等于 ,否则任何出度大于 的节点的子节点都不能放置混合器。
表示如果在 结点造一个巧克力混合器,最多能经过的牛奶数(每个点初始为 )。
用拓扑排序遍历整棵树,顺便计算 。
- 只需要找到入度为 的结点,标记并放入队列。
for (int i = 1; i <= n; i++)
if (!ind[i]) q.push(i), ans[i] = check[i] = 1, cnt++;
- 每次找孩子只需要找出度为 的结点。
对于每个点如果它的出度大于 ,那么他所连的边就不可能成为巧克力混合器。
- 对于每个结点 ,若 值等于总边数,且入度不为 ,就输出。
AC CODE
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 99;
int n, m, t, tot, cnt;
int head[maxn], out[maxn], ind[maxn];
int ans[maxn];
bool check[maxn];
struct Edge
{
int to, next;
} e[maxn];
void add(int a, int b)
{
e[++tot].to = b;
e[tot].next = head[a];
head[a] = tot;
}
void topo()
{
queue<int> q;
for (int i = 1; i <= n; i++)
if (!ind[i])
q.push(i), ans[i] = check[i] = 1, cnt++;
while (!q.empty())
{
int tmp = q.front();
q.pop();
if (out[tmp] == 1)
{
int j = head[tmp];
ans[e[j].to] += ans[tmp];
if (--ind[e[j].to] == 0)
q.push(e[j].to);
}
}
}
signed main()
{
cin >> n;
for (int i = 1, a, b; i < n; i++)
{
cin >> a >> b;
add(a, b);
out[a]++;
ind[b]++;
}
topo();
for (int i = 1; i <= n; i++)
{
if (ans[i] == cnt && !check[i])
{
cout << i << endl;
}
}
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18122194
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话