zoukankan      html  css  js  c++  java
  • CF796C Bank Hacking题解

    题目描述

    Although Inzane successfully found his beloved bone, Zane, his owner, has yet to return. To search for Zane, he would need a lot of money, of which he sadly has none. To deal with the problem, he has decided to hack the banks.

    imgThere are n n n banks, numbered from 1 1 1 to n n n . There are also n−1 n-1 n−1 wires connecting the banks. All banks are initially online. Each bank also has its initial strength: bank i i i has initial strength ai a_{i} ai .

    Let us define some keywords before we proceed. Bank i i i and bank j j j are neighboring if and only if there exists a wire directly connecting them. Bank i i i and bank j j j are semi-neighboring if and only if there exists an online bank k k k such that bank i i i and bank k k k are neighboring and bank k k k and bank j j j are neighboring.

    When a bank is hacked, it becomes offline (and no longer online), and other banks that are neighboring or semi-neighboring to it have their strengths increased by 1 1 1 .

    To start his plan, Inzane will choose a bank to hack first. Indeed, the strength of such bank must not exceed the strength of his computer. After this, he will repeatedly choose some bank to hack next until all the banks are hacked, but he can continue to hack bank x x x if and only if all these conditions are met:

    1. Bank x x x is online. That is, bank x x x is not hacked yet.
    2. Bank x x x is neighboring to some offline bank.
    3. The strength of bank x x x is less than or equal to the strength of Inzane's computer.

    Determine the minimum strength of the computer Inzane needs to hack all the banks.

    输入格式

    The first line contains one integer n n n ( 1<=n<=3⋅105 1<=n<=3·10^{5} 1<=n<=3⋅105 ) — the total number of banks.

    The second line contains n n n integers a1,a2,...,an a_{1},a_{2},...,a_{n} a1,a2,...,an ( −109<=ai<=109 -10^{9}<=a_{i}<=10^{9} −109<=ai<=109 ) — the strengths of the banks.

    Each of the next n−1 n-1 n−1 lines contains two integers ui u_{i} ui and vi v_{i} vi ( 1<=ui,vi<=n 1<=u_{i},v_{i}<=n 1<=ui,vi<=n , ui≠vi u_{i}≠v_{i} ui=vi ) — meaning that there is a wire directly connecting banks ui u_{i} ui and vi v_{i} vi .

    It is guaranteed that the wires connect the banks in such a way that Inzane can somehow hack all the banks using a computer with appropriate strength.

    输出格式

    Print one integer — the minimum strength of the computer Inzane needs to accomplish the goal.

    题意翻译

    给定一棵带点权树,选出一个最佳的根节点,使得根节点的点权不变,它的儿子点权加1,其余点点权加2,并使最大点权最小,输出这个最小的最大点权

    输入输出样例

    输入 #1

    5
    1 2 3 4 5
    1 2
    2 3
    3 4
    4 5
    

    输出 #1

    5
    

    输入 #2

    7
    38 -29 87 93 39 28 -55
    1 2
    2 5
    3 2
    2 4
    1 7
    7 6
    

    输出 #2

    93
    

    输入 #3

    5
    1 2 7 6 7
    1 5
    5 3
    3 4
    2 4
    

    输出 #3

    8
    

    说明/提示

    In the first sample, Inzane can hack all banks using a computer with strength 5 5 5 . Here is how:

    • Initially, strengths of the banks are [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] .
    • He hacks bank 5 5 5 , then strengths of the banks become [1,2,4,5,−] [1,2,4,5,-] [1,2,4,5,−] .
    • He hacks bank 4 4 4 , then strengths of the banks become [1,3,5,−,−] [1,3,5,-,-] [1,3,5,−,−] .
    • He hacks bank 3 3 3 , then strengths of the banks become [2,4,−,−,−] [2,4,-,-,-] [2,4,−,−,−] .
    • He hacks bank 2 2 2 , then strengths of the banks become [3,−,−,−,−] [3,-,-,-,-] [3,−,−,−,−] .
    • He completes his goal by hacking bank 1 1 1 .

    In the second sample, Inzane can hack banks 4 4 4 , 2 2 2 , 3 3 3 , 1 1 1 , 5 5 5 , 7 7 7 , and 6 6 6 , in this order. This way, he can hack all banks using a computer with strength 93 93 93 .

    题解

    Translation

    n个点,n-1条边组成的树,每个点价值为a[i],如果两点有边直接相连,这两点算相邻,如果存在三个点i,j,kik相邻,且 j也与k相邻则ij算半相邻。

    刚开始,每个点都在线状态,你有一个初始值x(待求),可以选择任意一点i(a[i]<=x)进行攻击,攻击i后,和i相邻和半相邻的点a[]++,同时i处于下线状态,要求攻击n个点需要的最小x?

    除了第一次外,每次攻击的点i必须满足:

    1. i必须在线
    2. i必须和某个处于离线状态的点相邻,
    3. a[i]<=x

    Attention

    接下来是我做题全过程中的关键:

    1.如果一个节点被攻击离线,则与其相邻的两个或多个节点就不是半相邻了.

    2.我们选第一个攻击的节点时,接下来不必顺着一条路径走,这种攻击方式有像BFS,向外扩散(不过这道题不用BFS).

    3.这是一棵树,所有点连通,n个点,n-1条边.

    4.(我找了1个小时的错才发现)注意数据范围,找Max时初始化为-1e9,而不是0;

    Solution

    首先可以知道,你如果用Max+2的值,任何情况的图都可以攻击成功.

    开始我想用一棵树模拟,具体就是通过枚举各个点作为初始要攻击的节点,因为我们知道,攻击一个节点会造成其邻节点与半邻节点加一,所以可以让这个选出的初始节点为根,直接相连的点+1,其余点+2,根节点不变,这就可以表示出来,攻击各个节点需要的最小值,在这各点的值中选最大值即可求出ans.

    为什么要枚举各个节点作为初始节点,而不是枚举各个最大节点作为根,原因就是可能有一种情况为

    image-20200430090613701

    这样明显选值为5的节点最优,ans = 7+1 = 8,如果选7,则ans = 7 + 2 = 9.

    好,这是一种方法,不过我在快写出来时觉得可能会T,因为遍历根节点再找最大值O((n^2)),也可能是我没想到更好的方法能优化了;

    另一种就是分类讨论了.

    最大值->Max

    最大值个数->cnt1

    最大值-1->Max-1

    最大值-1的个数->cnt2

    cnt1==1

    ​ 如果Max-1全是Max的邻节点,ans = Max;

    ​ else ans = Max+1;

    cnt1>=2

    ​ 如果全部Max是一个节点的邻节点,当然这个公共的邻节点可以是Max,则ans = Max+1;

    ​ else ans = Max+2;

    这种方法的第二种情况中找是否有一个节点邻接所有Max时,也就是遍历完边数的两倍(双向边),O(n),比上一种快不少.

    OK,完毕

    Code

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    const int maxn=3e5+5;
    struct Edge{int next,to;}e[maxn*2];
    int val[maxn],head[maxn],n,Max,c1,c2,cnt,pos;
    void Add(int u,int v){
    	e[++cnt].to=v;
    	e[cnt].next=head[u];
    	head[u]=cnt;
    }
    int main(){
    //	freopen("1.in","r",stdin);
    	scanf("%d",&n);
    	Max=-1e9;
    	for(int i=1;i<=n;++i){
    		scanf("%d",&val[i]);
    		if(Max<val[i])Max=val[i],pos=i;
    	}
    	for(int i=1;i<n;++i){int x,y;scanf("%d%d",&x,&y);Add(x,y),Add(y,x);}
    	for(int i=1;i<=n;++i){if(val[i]==Max)c1++;else if(val[i]==Max-1)c2++;}
    	if(c1==1){
    		if(c2==0)printf("%d
    ",Max);
    		else{
    			int cn=0;
    			for(int i=head[pos];i;i=e[i].next){int v=e[i].to;if(val[v]==Max-1)cn++;}
    			if(cn==c2)printf("%d
    ",Max);
    			else printf("%d
    ",Max+1);
    		}return 0;
    	}else{
    		bool adone=false;
    		for(int i=1;i<=n;++i){
    			int cn=0;
    			for(int x=head[i];x;x=e[x].next){
    				int v=e[x].to;
    				if(val[v]==Max)cn++;
    			}
    			if(val[i]!=Max&&cn==c1){adone=1;break;}
    			else if(val[i]==Max&&cn==c1-1){adone=1;break;}
    		}
    		if(adone)printf("%d
    ",Max+1);
    		else printf("%d
    ",Max+2);
    	}
    	return 0;
    }
    
  • 相关阅读:
    张一鸣:平常心做非常事|字节跳动9周年演讲全文
    实验二:分词
    helm部署EFK收集应用日志,ingress-nginx日志解析。
    Terraform
    Windows 11 下载
    Kubernetes Pod中容器的Liveness、Readiness和Startup探针
    Kubernetes使用Keda进行弹性伸缩
    K8s 部署 Prometheus + Grafana
    CSDN & 博客园
    zipkin,pinpoint和skywalking对比
  • 原文地址:https://www.cnblogs.com/Lour688/p/12806808.html
Copyright © 2011-2022 走看看