1. 程式人生 > >cf796c 樹形,思維題

cf796c 樹形,思維題

一開始以為是個樹形dp,特地去學了。。結果是個思維題

/*
樹結構,設最大點權值為Max,則答案必在在區間[Max,Max+2]
證明ans <= Max+2
任取一個點作為根節點,那麼去掉這個點之後其兒子結點,孫子結點的權值+1,同理,每去掉一個點之後其兒子結點,孫子結點的權值都會加上1
即每個點的權值最多隻能被+2,即它的父親,爺爺結點會導致其增加權值
考慮什麼時候ans=Max:只有一個Max結點,以其為根,若有權值Max-1的點,那麼這些點只有一個父親就是Max 
ans=Max+1:所有的Max有相同的父親 
怎麼判斷 
*/
#include<bits/stdc++.h>
using
namespace std; #define maxn 300005 struct Edge{ int to,next; }edge[maxn<<2]; int head[maxn],tot,n,a[maxn]; void init(){ memset(head,-1,sizeof head); tot=0; } void addedge(int u,int v){ edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } int main(){ int Max=-1000000007,tot1=0
,tot2=0,u,v,x; init(); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); Max=max(Max,a[i]); } for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } for(int i=1;i<=n;i++) if(Max==a[i]) tot1++,u=i;
else if(Max-1==a[i]) tot2++; int tmp=0; if(tot1==1){//只有一個Max for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(a[v]==Max-1)tmp++; } if(tmp==tot2)//所有Max-1都是其子節點 printf("%d",Max); else printf("%d",Max+1); return 0; } int vis[maxn]={},flag=0; queue<int>q; q.push(1);vis[1]=1; while(!q.empty()){ int u=q.front();q.pop();vis[u]=1; int tmp=a[u]==Max?1:0; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(!vis[v]) q.push(v); if(a[v]==Max)tmp++; } if(tmp==tot1){ flag=1;break; } } if(flag) printf("%d",Max+1); else printf("%d",Max+2); }