zoukankan      html  css  js  c++  java
  • 2020年HDU多校第二场 1001 Total Eclipse(思维)

    2020年HDU多校第二场 1001 Total Eclipse(思维)

    Total Eclipse

    题意:每次选一个连通块使里面所有点的值减一,当某个点减为零时其点连的所有边都会删去,求多少次操作使所有点变成0。

    题解:这个题感觉还是比较难想的,比赛时想了2个多小时也没想到;

    先给个样例:

    1

    3 2

    1 2 3

    3 1

    1 2

    可以将图画成柱形图(关系复杂的图不好画,这里是方便理解):

    显然答案为4,高度为一,切1刀,剩一个2与1不连通一共切3刀,共四次,那么我们是不是也可以反过来想,我将3号最上面切一刀与2等高,将3与2分别再切一刀与1等高,此时1将3与2连通,再一起切一刀。那么反过来想的好处是什么呢,正推是原本连通的点将不连通,要花o(n)时间重新建图,而反推,连通的点继续连通,新加进来的点可能将更多点连通,具有单调性,即可以优化大量时间,怎么记录连通关系啥的就不多说了,并查集搞一搞,cnt记录一下连通块数量既可

    #include<iostream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll long long
    ll to,t,n,m,u,v,fa[100007],vis[100007],cnt,h,ans,lin;
    struct madoka{
        ll p;
        ll h;
    }a[100007],now;
    ll fin(ll p){
        if(p==fa[p])return p;
        else{
            return fa[p]=fin(fa[p]);
        }
    }
    bool cmp(madoka a1,madoka a2){
        return a1.h>a2.h;
    }
    vector<int>ho[100007];
    void init(){
        for(int i=1;i<=n;i++)ho[i].clear(),vis[i]=0;
    }
    int main(){
        scanf("%lld",&t);
        while(t--){
            scanf("%lld%lld",&n,&m);
            init();
            for(int i=1;i<=n;i++){
                scanf("%lld",&a[i].h);
                a[i].p=i;
                fa[i]=i;
            }
            for(int i=1;i<=m;i++){
                scanf("%lld%lld",&u,&v);
                ho[u].push_back(v);
                ho[v].push_back(u);
            }
            sort(a+1,a+1+n,cmp);
            h=a[1].h;
            vis[a[1].p]=1;
            cnt=1;
            ans=0;
            for(int i=2;i<=n;i++){
                now=a[i];
                lin=(h-a[i].h);
                ans=(ans+lin*cnt);
                for(int j=0;j<ho[now.p].size();j++){
                    to=ho[now.p][j];
                    if(fin(now.p)!=fin(to)&&vis[to]){
                        cnt--;
                        fa[fin(now.p)]=fin(to);
                    }
                }
                vis[now.p]=1;
                h=a[i].h;
                cnt++;
            }
            ans=(ans+h*cnt);
            printf("%lld
    ",ans);
        }
    }
    
  • 相关阅读:
    python 小爬虫
    动态规划,网易秋招
    leetcode 3
    leetcode 27 水
    leetcode 21 list merge
    leetcode 15 3sum & leetcode 18 4sum
    leetcode 389 map iterator 的使用
    [转]使用flask实现mock server
    python __str__repr__ 区别
    Robot Framework 源码阅读 day2 TestSuitBuilder
  • 原文地址:https://www.cnblogs.com/whitelily/p/13372615.html
Copyright © 2011-2022 走看看