zoukankan      html  css  js  c++  java
  • COJ 1700:联通与次联通

    题意:有N个人,M对关系,同时给出每个人的贡献c[i]。要求对于每一个人以及他认识的所有人,收入按照贡献由高到低不矛盾,求最小的总收入

    思路:从最小贡献的人开始考虑。可以想到影响他收入的人只能是和他联通的人以及次联通的人,那他的收入就是这些人中比他贡献低的人的收入max+1

    对于某人次联通的人来说,两者之间肯定有一个共同认识的人,由题意可以得出两者也会影响

    一开始想到了从最小贡献的人开始考虑,但是不清楚次联通怎么处理。。

    这里难的地方就在于如何快速找到某个点的联通和次联通的所有点中的最小值

    这里还要注意一个地方就是相同贡献的要作为一组同时处理

    因为从贡献最小的开始处理后,得到他的工资后就无用了,所以我们用他的工资来处理和他联通的点

    这样做的话,该点的次联通就只需要查询公共点的cost就能够判断

    注意代码中的cost不是表示工资,cost[i]=j表示的是第i个点以及其联通的点中最大工资为j

    #include"cstdio"
    #include"queue"
    #include"cmath"
    #include"stack"
    #include"iostream"
    #include"algorithm"
    #include"cstring"
    #include"queue"
    #include"map"
    #include"set"
    #include"vector"
    #define LL long long
    #define mems(a,b) memset(a,b,sizeof(a))
    #define ls pos<<1
    #define rs pos<<1|1
    #define max(a,b) (a)>(b)?(a):(b)
    using namespace std;
    
    const int N = 1e5+5;;
    const int MAXN = 200;
    const int INF = 0x3f3f3f3f;
    
    struct node{
        int w,id;
    }c[N];
    
    vector<int> G[N],vec;
    int cost[N],d[N],tmp[N];
    LL ans;
    
    bool cmp(node a,node b){
        return a.w<b.w;
    }
    
    void update(vector<int> &vec){
        for(int i=0;i<vec.size();i++){
            int u=vec[i];
            int maxv=0;
            for(int j=0;j<G[u].size();j++){
                int v=G[u][j];
                //if(d[v]<=d[u])
                maxv=max(maxv,cost[v]);
            }
            tmp[u]=maxv+1;
            //cout<<u<<' '<<tmp[u]<<endl;
            ans+=(LL)tmp[u];
        }
        for(int i=0;i<vec.size();i++){
            int u=vec[i];
            cost[u]=tmp[u];
            for(int j=0;j<G[u].size();j++){
                int v=G[u][j];
                //if(d[v]>=d[u])
                cost[v]=cost[u];
            }
        }
        vec.clear();
    }
    
    int main(){
        int n,m;
        //freopen("in.txt","r",stdin);
        while(~scanf("%d",&n)){
            for(int i=1;i<=n;i++) G[i].clear();
            mems(cost,0);
            for(int i=1;i<=n;i++){
                scanf("%d",&d[i]);
                c[i].id=i;
                c[i].w=d[i];
            }
            sort(c+1,c+n+1,cmp);
            scanf("%d",&m);
            for(int i=0;i<m;i++){
                int a,b;
                scanf("%d%d",&a,&b);
                G[a].push_back(b);
                G[b].push_back(a);
            }
            vec.clear();
            int k=1;
            ans=0;
            while(k<=n){
                while(vec.empty()||d[c[k].id]==d[c[k-1].id])
                    vec.push_back(c[k++].id);
                update(vec);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Redis过期key是怎么样清理的?----互联网大厂面试题
    Docker容器引擎使用教程
    区块链算法
    MYSQL 常用语句与函数命令
    漏洞利用:验证绕过,XSS利用,Cookic盗用,文件上传
    小白网工入行要具备哪些基本技能?
    VMware中乌班图安装VMtools步骤
    防火墙技术原理-思维导图
    JAVA学习第一课-手工笔记
    DOS(磁盘操作系统)基本命令-思维导图
  • 原文地址:https://www.cnblogs.com/luxiaoming/p/5281109.html
Copyright © 2011-2022 走看看