CF796C Bank Hacking

题目链接

分析

题目好长
其实也不是很长,我感觉按照原题的说法去理解这个题会比较好理解一些。
就是说,我先从树上找到一个点,然后一步一步的去覆盖这棵树,你只能覆盖点权比你小的点,问覆盖整棵树需要你的权值最小是多少。
首先先考虑我会去从哪个点开始,显然是先覆盖点权大的,因为它迟早都要被覆盖,如果现在不去覆盖,那再覆盖它,它的点权就会增加,所以肯定要先覆盖点权大的,进而可以知道,一个点如果有可能成为最大值,它的点权最多只会被+2,因为我要去覆盖它,首先覆盖它的半相邻点,再去覆盖它的相邻点,
如果它变大了,那我下一步就要把它覆盖掉,因此答案最多只可能是最大值+2。
接下来就是一个分类讨论了,假设最大值为\(max\),我们只要找\(max-1\)的点就行了,因为\(max-2\)的点最多也只会被搞成\(max\),如果所有的\(max-1\)的点都连在\(max\)上,那我搞完\(max\)就能在他们增加1到\(max-1+1\)的时候,破坏掉他们,所以此时答案为\(max\),如果一个\(max-1\)的点也没有,那答案显然也是这个。

如果他们不连在一起呢?

那我覆盖\(max\)和6的时候,\(max-1\)都要+1,最后就成了\(max+1\),所以当没有连在一起的时候,就是\(max+1\)
那么有不止一个\(max\)的时候呢?

如果这些都连在一起,答案是\(max+1\),不管是连在\(max\)上还是别的上边,只要他们互为相邻点或半相邻点就好。

那么跟上边推\(max-1\)的时候一样,只不过\(max\)最多变成\(max+2\)
也就这几种情况了,模拟一下就出来??

#include<cstdio>
#include<limits>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e5+10;
struct Edge{
    int to,nxt;
}e[N<<1];
int h[N],idx,w[N];
void Ins(int a,int b){
    e[idx].to=b;e[idx].nxt=h[a];h[a]=idx++;
}
int main(){
    memset(h,-1,sizeof(h));
    int n,mx,cnt,cntsec,pos;
    mx=INT_MIN;cntsec=cnt=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&w[i]);
        if(w[i]>mx){
            mx=w[i];
            pos=i;
        }
    }
    for(int i=1;i<=n;i++){
        if(w[i]==mx)cnt++;
        if(w[i]==mx-1)cntsec++;
    }
    for(int i=1;i<n;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        Ins(a,b);
        Ins(b,a);
    }
    if(cnt==1){
        if(cntsec==0){
            printf("%d\n",mx);
            return 0;
        }
        int nxt=0;
        for(int i=h[pos];~i;i=e[i].nxt){
            if(w[e[i].to]==mx-1)nxt++;
        }
        if(nxt==cntsec)
            printf("%d\n",mx);
        else printf("%d\n",mx+1);
        return 0;
    }
    if(cnt>1){
        for(int i=1;i<=n;i++){
            int nxt=0;
            for(int j=h[i];~j;j=e[j].nxt){
                if(w[e[j].to]==mx)nxt++;
            }
            if((nxt==cnt&&w[i]!=mx)||(nxt==cnt-1&&w[i]==mx)){
                printf("%d\n",mx+1);
                return 0;
            }
        }
    }   
    printf("%d\n",mx+2);
    return 0;
}
posted @ 2020-04-30 09:27  An_Fly  阅读(136)  评论(0编辑  收藏  举报