Chocolate Milk(洛谷P2999)

传送门

拓扑排序

关于拓扑排序,这里不叙述太多,可参考本人CSDN

值得注意的是,这不是一棵树吗?

FJ 发现对于牛奶来说有一种最多的方式从一个接口流到另一个接口。并且由于 FJ 是一个高效率的人,他需要确保每一个管道都有牛奶经过,也就是说,没有多余的管道。

所以,对于牛奶来说,最多只有一种方式从一个接口流到另一个接口。则不会有牛奶分开又聚到一起。

故有一个性质:除非节点的入度等于 00,否则任何出度大于 11 的节点的子节点都不能放置混合器。

ansians_i 表示如果在 ii 结点造一个巧克力混合器,最多能经过的牛奶数(每个点初始为 11)。

用拓扑排序遍历整棵树,顺便计算 ansans

  1. 只需要找到入度为 00 的结点,标记并放入队列。
for (int i = 1; i <= n; i++)
		if (!ind[i]) q.push(i), ans[i] = check[i] = 1, cnt++;
  1. 每次找孩子只需要找出度为 11 的结点。

对于每个点如果它的出度大于 11,那么他所连的边就不可能成为巧克力混合器。

  1. 对于每个结点 xx ,若 ansxans_x 值等于总边数,且入度不为 00,就输出。

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;
        }
    }
}
posted @   蒟蒻orz  阅读(8)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示