zoukankan      html  css  js  c++  java
  • Code Forces 796C Bank Hacking(贪心)

    Code Forces 796C Bank Hacking

    题目大意

    给一棵树,有(n)个点,(n-1)条边,现在让你决策出一个点作为起点,去掉这个点,然后这个点连接的所有点权值+=1,然后再将这些刚刚加过一的点的相邻的点的权值+=1
    也就是说,除了与根节点相邻的点+=1,其余点+=2
    然后求最大集合的最小点权

    solution

    一看是要求最大的的最小值,首先想到的就是二分,显然想到这个目前没有什么卵用,二分是用来卡最佳答案的,所以使用二分的前提是要给它一个范围去选择,那么现在的任务就是去找这个答案的集合,并且希望它是一个有序的集合,这样我们才能二分答案。

    预处理时分情况讨论,max,max+1,max+2

    • (root)链接的点只有(1)(max):则所有(max-1)都和(root)相邻或者均为(max),更新(ans = max),其他的情况就是(ans = max + 1)
    • (root)连接的点中有多个(max),那么当所有(max)和其中一个相邻的时候(ans=max+1),剩下的情况,(ans=max+2)

    代码——pl.()

    #include <cstdio>
    #include <string>
    using namespace std;
    const int maxn=3*1e5+10;
    int a[maxn];
    struct E{
        int next;
        int to;
        E(){
            to=next=0;
        }
    }ed[maxn*2];
    int head[maxn];
    int tot;
    void J(int a,int b){
        tot++;
        ed[tot].to=b;
        ed[tot].next=head[a];
        head[a]=tot;
    }
    int main(){
        int n;
        scanf("%d",&n);
        int ma=-1e9-10;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            ma=max(ma,a[i]);
        }
        int j1,j2;
        for(int i=1;i<=n-1;i++){
            scanf("%d%d",&j1,&j2);
            J(j1,j2);
            J(j2,j1);
        }
        int js1=0,js2=0;//表示ma和ma-1的个数
        for(int i=1;i<=n;i++){
            if(a[i]==ma)
                js1++;
            if(a[i]==ma-1)
                js2++;
        }
        if(js1==1){//分情况处理一下
            int js=0;
            for(int i=1;i<=n;i++)
                if(a[i]==ma){
                    for(int j=head[i];j;j=ed[j].next)
                        if(a[ed[j].to]==ma-1)
                            js++;
                    break;
                }
            if(js==js2)
                printf("%d",ma);
            else
                printf("%d",ma+1);
        }
        else{
            int js=0;
            int zjs=0;
            for(int i=1;i<=n;i++){
                if(a[i]==ma)
                    zjs++;
                for(int j=head[i];j;j=ed[j].next)
                    if(a[ed[j].to]==ma)
                        zjs++;
                js=max(js,zjs);
                zjs=0;
            }
            if(js==js1)
                printf("%d",ma+1);
            else
                printf("%d",ma+2);
    
        }
        return 0;
    }
    
  • 相关阅读:
    向量旋转公式推导
    atan函数与atan2函数
    UVALive 7040 Color (容斥原理+逆元+组合数+费马小定理+快速幂)
    关于source insight、添加.s和.S文件,显示全部路径、加入项目后闪屏幕
    linux内核设计与实现--进程调度 系统调用
    linux内核设计与实现--进程管理
    linux命令行与shell脚本编程大全---bash shell命令
    linux内核设计与实现--从内核出发
    Linux内核学习之路
    NAND FLASH均衡算法笔记(转)
  • 原文地址:https://www.cnblogs.com/rui-4825/p/12809593.html
Copyright © 2011-2022 走看看