http://codeforces.com/contest/796/problem/C
题意:给一颗树,删除节点,每次删除节点会使未被删除邻居和未被删除邻居的邻居权+1,问删除整棵树遇到最小的最大权是多少。 第一次以后的删除只能删除已被删除节点的邻居。
想要使答案尽量的小则优先选择权大的删除。 考虑到一个节点最多只能+2,假设ai最大值为mx,则答案可能为mx , mx +1 , mx +2。 而权为mx-1的节点最大权值可以达到mx+1,同样可以影响答案。
答案为mx的时候一定只有一个权为mx的节点 , 如果有多个则后面删除的初始权为mx的节点的权一定会改变 。 如果有权mx-1的节点则一定要与权为mx的节点相连,否则一定有权为mx-1的点权值+2。
接下来讨论答案为mx+1的情况,权为mx-1的节点可以创造的最大权值为mx+1所以可以忽略。权为mx的节点可以创造的最大价值为mx+2,所以研究关于权为mx的节点的限制条件。
若答案为mx+1,则每个权为mx的节点一定最多只+1了一次。 假设有x个权为mx的节点 则一定有1个节点与x-1个节点相连。 否则x个节点中一定有节点将会+2。
答案不为mx和mx+1时即答案为mx+2 然后对于每种情况做判断就行了
#include <iostream> #include <algorithm> #include <sstream> #include <string> #include <queue> #include <cstdio> #include <map> #include <set> #include <utility> #include <stack> #include <cstring> #include <cmath> #include <vector> using namespace std; #define pb push_back #define scand(n) scanf("%d",&n) #define scandd(n,m) scanf("%d%d",&n,&m) #define scanddd(n,m,k) scanf("%d%d%d",&n,&m,&k) #define scanlld(n) scanf("%lld",&n) #define scanlldd(n,m) scanf("%lld%lld",&n,&m) #define scanllddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k) #define scans(str) scanf("%s",str) #define ans() printf("%d",ans) #define ansn() printf("%d\n",ans) #define anss() printf("%d ",ans) #define llans() printf("%lld",ans) #define llanss() printf("%lld ",ans) #define llansn() printf("%lld\n",ans) #define REP(i,n) for(int i=0;i<(n);++i) #define REA(i,qwe,ewr) for(int i=qwe;i<=ewr;++i) #define RER(i,qwe,ewr) for(int i=qwe;i>=ewr;--i) #define mst(abc,bca) memset(abc,bca,sizeof abc) #define pii pair<int,int> typedef long long ll; const int mod = 1000000007; const double eps=1e-9; const int INF=0x3f3f3f3f; const int MAXN=300005; int a[MAXN]; vector<int>v[MAXN]; int ct1[MAXN],ct2[MAXN]; int main() { #ifdef LOCAL freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // LOCAL int n; scand(n); int mx =-1e9; for(int i=1;i<=n;++i){ scand(a[i]); mx = max(mx,a[i]); } for(int i=1;i<n;++i){ int a,b; scandd(a,b); v[a].pb(b); v[b].pb(a); } int cnt1=0,cnt2=0,id=-1; int m1=0,m2=0; for(int i=1;i<=n;++i) { if(a[i]==mx) { ct1[i]++; ++cnt1; for(int j=0;j<v[i].size();++j)ct1[ v[i][j] ]++; id = i; } else if (a[i] == mx-1) { ct2[i]++; ++cnt2; for(int j=0;j<v[i].size();++j)ct2[ v[i][j] ]++; } } for(int i=1;i<=n;++i) m1 = max(m1,ct1[i]) , m2 = max(m2,ct2[i]); if(cnt1==1&&ct2[id]==cnt2)printf("%d",mx); else if(cnt1==m1)printf("%d",mx+1); else printf("%d",mx+2); return 0; }