码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Global Round 8 E. Ski Accidents

时间:2020-06-20 17:04:50      阅读:79      评论:0      收藏:0      [点我收藏+]

标签:out   ref   ble   int   ide   最大的   bsp   ack   def   

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

题意

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

题解

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

证明

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

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

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

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

化简得:

\begin{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() << "\n";
    for (auto i : ans) cout << i << " \n"[i == ans.back()];
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

 

Codeforces Global Round 8 E. Ski Accidents

标签:out   ref   ble   int   ide   最大的   bsp   ack   def   

原文地址:https://www.cnblogs.com/Kanoon/p/13168766.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!