CF796C Bank Hacking

题意

  给一个n个点,n-1条边的连通图,每个点一个值,一开始选任意一点开始访问,访问一点后,这个点从图中消失,和它相邻和相距一个点的点+1,接下来能访问和它相邻的点,求访问的点的最大值。

思路

  选定一个点开始访问,ans={,它,周围一圈+1,其余+2} 

  当max存在1个以上,ans=max+1或max+2.

  如果存在一个点,所有max都在其1格内 ans=max+1,or ans=max+2

  max只有一个时,如果所有max-1都在其1格范围内,ans=max or ans=max+1;

  其他情况都是ans=max

检查了四个小时的原因(!!)

  1.最小值为-1e9,max的一开始初始值设了0(数据范围)

  2.一开始的思路没有化到最简,还dfs了点的第2层,十分烦(当感觉自己的思路有点烦时,要再多想想)

  3.(最最浪费时间的一点)最最开始的思路错了,认为要第一个访问的点一定要是最大值的点。(要保证每一步的准确性)

代码

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<map>
#define INF 0x7f7f7f7f
#define MAX_INT 0x7fffffff
#define pi 3.1415926
typedef long long LL;
typedef unsigned int uint;
using namespace std;
vector<int>t[300005]; 
int num[300005];
int ns,ni;
int maxx=-MAX_INT,nma;
/*
当max存在1个以上,ans=max+1或max+2.
如果存在一个max,所有max都在其1格内 ans=max+1,or ans=max+2
max只有一个时,如果所有max-1都在其1格范围内,ans=max or ans=max+1;
其他情况都是ans=max 
*/
int cnt;
int search(int pos,int c){
    int si=t[pos].size();
    if(!c){
        for(int i=0;i<si;i++){
            if(num[t[pos][i]]==maxx-1)cnt++;
        }
        if(cnt==nma)return 0;
        else return 1;
    }
    else{
        for(int i=0;i<si;i++){
            if(num[t[pos][i]]==maxx){
                cnt++;
            }
        }
        if(cnt<ns)return 2;
        else return 1; 
    }
}
int main(){ 
    int n;register int i,a,b;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        scanf("%d",&num[i]);
        if(maxx<num[i]){
            maxx=num[i];
        }
    }
    for(i=1;i<=n;i++)
        if(num[i]==maxx){ns++;ni=i;}
        else if(num[i]==maxx-1)nma++;
    for(i=1;i<n;i++){
        scanf("%d%d",&a,&b);
        t[a].push_back(b);
        t[b].push_back(a);
    }
    int ans=5;
    if(ns>1){
        for(i=1;i<=n;i++){
            cnt=0;
            if(num[i]==maxx)cnt++;
            ans=min(ans,search(i,1));
        }        
    }
    else{
        ans=search(ni,0);
    }
    printf("%d\n",ans+maxx);
    return 0;
}

 

转载于:https://www.cnblogs.com/Gsimt/p/10110421.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值