CF1890D Doremy's Connecting Plan

传送门。我们发现 c 对于问题的影响不大,我们可以将每个 ai 除以 c,就转化为了 c=1 的情况。一个自然的贪心是用 1 作为中心点去连接其他的所有点,这需要两条结论保证其正确性:

结论一: 如果当前图中还可以连边,点 1 就还可以与其他点连边。

假设我们能够在点 i,j1 之间连边的话,有以下不等式成立 Si+Sjiji+j,其中 Si 表示点 i 所属连通块的点权和(第二个不等号可以通过简单的数学推导得出)。此时必有 Sii 或者 Sjj(反证法,若 Si<iSj<jSi+Sj<i+j,矛盾)。不妨设 Sii,有 Si+S1i1,所以 1,i 之间一定可以连边。

结论二: 以点 1 为中心点连边,不会导致“本来能连上的点”连不上了。

假如点 i,j 之间能连边,由结论一得,必有 1,i1,j 之间能连边,则任意点都能与 1 间接连通,但能否直接连通呢?难以证明。

就本题而言,我们继续贪心地认为,只要 1 连接起来的连通块足够大,点权和就能够保证不等式的成立。所以可以把节点按照 Sii 从大到小排序,先易后难(显然 Sii 大时不等式 Si+S1i1 更容易成立),逐一与点 1 结合,如果不能结合则认为无法连通,输出 NO

void solve() {
    int n;
    i64 c;
    cin >> n >> c;
    cin >> $( a, n );
    iota( all( b, n ), 1 );
    sort( all( b, n ), [&]( int x, int y ) {
        return a[x] - x * c > a[y] - y * c;
    } );
    i64 s = a[1];
    forn( i, n ) {
        if( b[i] == 1 ) ctn;
        if( s + a[b[i]] < b[i]*c ) {
            cout << "No\n";
            return;
        }
        s += a[b[i]];
    }
    cout << "Yes\n";
    clear();
}
posted @   XYukari  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示