zoukankan      html  css  js  c++  java
  • 【2020杭电多校】Total Eclipse 并查集+思维

    题目链接:Total Eclipse

    题意:

    t组输入,给你一个由n个点,m条边构成的图,每一个点的权值是ai。你每一次可以选择一批联通的点,然后让他们的权值都减去1。问最后把所有点的权值都变成0需要多少次操作

    题解:

    最简单的思路就是每一次dfs找到图中联通的最长的链,然后让这条链减去链上所有点中那个最小的权值。之后这条链就断了。然后再去找链,,依次。。但是这样复杂度太高了,就会TLE

    如果每一次找到的链上所有点的权值是有序的,那么我们就可以一次得到将这条链上的点的权值变成0的最小操作数,比如下面一条权值链

    9->8->7->6->2->1,那么把这些点权值变成0只需要9次

    那么我们可以从新构建一下这个图,我们可以按照这些点的权值从大到小排序,然后遍历它,先找到一个点,那么这个点就独自构成一个连通块,如果下一个点和之前点相连,那么这两个点就在一个连通块上,连通块数量不加1,否则连通块数量加1(如果这个点将多个连通块相连,那么连通块个数就不止减1了)。我们先说连通块数量减1情况,我们的答案要加上(a[2]-a[3])*ans (ans是连通块数量,a数组就是题目上的权值数组),他代表的意思就是a[2]点相对于a[3]点要多做几次操作,乘于ans是,有ans个连通块都需要多做a[2]-a[3]次操作。(在加入第一个点的时候也要进行这样的操作)

    模拟过程可以看一下这篇博客:https://blog.csdn.net/yangzijiangac/article/details/107559199

    代码:

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <vector>
    #include <map>
    #include <queue>
    #include <set>
    #include <ctime>
    #include <cstring>
    #include <cstdlib>
    #include <math.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    vector<ll>w[maxn];
    ll n,m,v[maxn],vis[maxn];
    struct shudui
    {
        ll pos,val;
    }a[maxn];
    bool mmp(shudui x,shudui y)
    {
        return x.val>y.val;
    }
    ll finds(ll x)
    {
        if(x!=v[x])
        {
            ll y=finds(v[x]);
            v[x]=y;
            return y;
        }
        return x;
    }
    int main()
    {
        ll t;
        scanf("%lld",&t);
        while(t--)
        {
            memset(vis,0,sizeof(vis));
            scanf("%lld%lld",&n,&m);
            for(ll i=1;i<=n;++i)
                w[i].clear();
            for(ll i=1;i<=n;++i)
            {
                v[i]=i;
                scanf("%lld",&a[i].val);
                a[i].pos=i;
            }
            sort(a+1,a+1+n,mmp);
            a[n+1].val=0;
            while(m--)
            {
                ll x,y;
                scanf("%lld%lld",&x,&y);
                w[x].push_back(y);
                w[y].push_back(x);
            }
            ll sum=0,ans=0;
            for(ll i=1;i<=n;++i)
            {
    
                ans++;
                ll x=a[i].pos;vis[x]=1;
                for(ll j=0;j<w[x].size();++j)
                {
    
                    ll pos=w[x][j];
                    if(vis[pos])
                    {
                        ll fx=finds(x);
                        ll fy=finds(pos);
                        if(fx!=fy)
                        {
                            v[fx]=fy;ans--;
                        }
                    }
                }
                sum=sum+ans*(a[i].val-a[i+1].val);
            }
            printf("%lld
    ",sum);
        }
        return 0;
    }
  • 相关阅读:
    洛谷—— P1196 银河英雄传说
    MySQL练习题参考答案
    January 16 2017 Week 3 Monday
    January 15 2017 Week 3 Sunday
    January 14 2017 Week 2nd Saturday
    January 13 2017 Week 2 Friday
    January 12 2017 Week 2 Thursday
    January 11 2017 Week 2nd Wednesday
    January 10 2017 Week 2nd Tuesday
    January 09 2017 Week 2nd Monday
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/13376225.html
Copyright © 2011-2022 走看看