Crazy Bobo
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 1882 Accepted Submission(s): 639
Problem Description
Bobo has a tree,whose vertices are conveniently labeled by 1,2,…,n.Each node has a weight wi. All the weights are distrinct.
A set with m nodes v1,v2,…,vm is a Bobo Set if:
- The subgraph of his tree induced by this set is connected.
- After we sort these nodes in set by their weights in ascending order,we get u1,u2,…,um,(that is,wui < wui+1 for i from 1 to m-1).For any node x in the path from ui to ui+1(excluding ui and ui+1),should satisfy wx < wui.
Your task is to find the maximum size of Bobo Set in a given tree.
Input
The input consists of several tests. For each tests:
The first line contains a integer n (1≤n≤500000). Then following a line contains n integers w1,w2,…,wn (1≤wi≤109,all the wi is distrinct).Each of the following n-1 lines contain 2 integers ai and bi,denoting an edge between vertices ai and bi (1≤ai,bi≤n).
The sum of n is not bigger than 800000.
Output
For each test output one line contains a integer,denoting the maximum size of Bobo Set.
Sample Input
7
3 30 350 100 200 300 400
1 2
2 3
3 4
4 5
5 6
6 7
Sample Output
5
【分析】
题意:
n个点,每个点都有权值。n-1条边构成树。求一个最大集合,使得集合中的所有点联通,且按照点的权值排列之后相邻两个点之间的路径上的点的权值都要比起点小。
比较奇妙的一道题
乍一看不会做…再一看还不会做..向题解低头
思路:
题目转化为以一个点作为权值最小点,以权值递增的规则看它能到达多少个点。
将无向图建成有向图,权值小的点指向权值大的点。
使用dfs,进行记忆化搜索,num数组记录该点的子树节点数量。
这样将问题转化,就可以裸跑dfs
【代码】
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
const int mxn=5e5+5;
int n,ans,cnt;
int val[mxn],num[mxn],head[mxn];
struct edge {int to,next;} f[mxn*2];
inline void add(int u,int v)
{
f[++cnt].to=v;
f[cnt].next=head[u];
head[u]=cnt;
}
inline int dfs(int u)
{
if(num[u]) return num[u];
num[u]=1;
for(int i=head[u];i;i=f[i].next)
{
int v=f[i].to;
num[u]+=dfs(v);
}
ans=max(ans,num[u]);
return num[u];
}
int main()
{
int u,v;
while(scanf("%d",&n)==1)
{
cnt=0;
memset(head,0,sizeof head);
memset(num,0,sizeof num);
fo(i,1,n) scanf("%d",&val[i]);
fo(i,2,n)
{
scanf("%d%d",&u,&v);
if(val[u]<val[v]) add(u,v);
else add(v,u);
}
ans=1;
fo(i,1,n) dfs(i);
printf("%d\n",ans);
}
return 0;
}