• Codeforces Global Round 8 E. Ski Accidents(拓扑排序)


    题目链接:https://codeforces.com/contest/1368/problem/E

    题意

    给出一个 $n$ 点 $m$ 边的有向图,每条边由编号较小的点通向编号较大的点,每个点的出度不大于 $2$,删掉一些点,使得图中不存在长度大于等于 $2$ 的路径。(最多删掉 $frac{4}{7}n$ 个点)

    题解

    删除所有拓扑排序中深度为 $3$ 的倍数的顶点,由于每次删掉了一层,所以把所有点深度置为 $1$,只删除深度为 $3$ 的顶点即可。

    证明

    删除点占比最大的情况是该有向图为满二叉树且深度为 $3$ 的倍数,要删除的点即深度为 $3$ 的倍数每层结点,删除结点的个数与满二叉树结点的总个数之比为:

    egin{equation} frac{2^2 + 2^5 + dots + 2^{3n - 1}}{2^0 + 2^1 + 2^2 + dots + 2^{3n - 1}} end{equation}

    分子分母等比数列求和得:

    egin{equation} frac{ frac{4(1 - 8^n)}{1 - 8} }{ frac{(1 - 2^{3n})}{1 - 2} }  end{equation}

    化简得:

    egin{equation} frac{4}{7}  end{equation}

    即最多删除 $frac{4}{7}n$ 个结点。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    void solve() {
        int n, m; cin >> n >> m;
        vector<int> G[n + 1];
        for (int i = 0; i < m; i++) {
            int u, v; cin >> u >> v;
            if (u == v) continue;
            G[u].push_back(v);
        }
        vector<int> ans;
        vector<int> dis(n + 1, 1);
        for (int u = 1; u <= n; u++) {
            if (dis[u] == 3) {
                ans.push_back(u);
                continue;
            }
            for (auto v : G[u])
                dis[v] = max(dis[v], dis[u] + 1);            
        }
        cout << ans.size() << "
    ";
        for (auto i : ans) cout << i << " 
    "[i == ans.back()];
    }
    
    int main() {
        int t; cin >> t;
        while (t--) solve();
    }
  • 相关阅读:
    IEnumerable、IEnumerator接口(如何增加迭代器功能)
    IConvertible接口
    IComparable和IComparer接口
    c#-泛型、协变、逆变
    MVC-HtmlHelper扩展
    .Net反射-TypeDescriptor
    MVC Core 使用TagHelper扩展几个插件
    js日志组件封装
    js预解析
    js代码优化
  • 原文地址:https://www.cnblogs.com/Kanoon/p/13168766.html
Copyright © 2020-2023  润新知