解题报告 之 HDU5325 Crazy Bobo
Description
Bobo has a tree,whose vertices are conveniently labeled by 1,2,...,n.Each node has a weight .
All the weights are distrinct.
A set with m nodes 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 ,(that
is, for
i from 1 to m-1).For any node in
the path from to (excluding and ),should
satisfy .
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 ().
Then following a line contains n integers (,all
the is
distrinct).Each of the following n-1 lines contain 2 integers and ,denoting
an edge between vertices and ().
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条无向边并给出每个点的权值。让你找一个最大的子图满足子图中的连接权重相邻的两点 u,v 的道路中任意节点x的权值都比u、v的小。(其实好像看题的时候没看出来是这个意思,查了下才知道)。
分析:因为这个子图任意权重相邻的点都要满足这个条件,所以这个子图一定连通(否则一定存在权值相邻的点之间没有连通path)。然后注意到这个条件,这个子图任意权重相邻点之间的路要么是没有点,要么一定是呈现山谷状的,即两边最高,向中间递减。那么从图中的一个点开始,以它为最低点,向两边较高的扩展,然后再以同样的方式去搜索这两个较高点。那么任意两个权值相邻的点,往回找通路的时候一定都是呈现山谷状的。那么问题就转换成了,从某个点出发,去找到它能够扩展到的最大点数,深搜一次即可。
上代码:
#include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int MAXN = 5e6+10; struct Edge { int to, nxt; }; Edge edge[MAXN]; int head[MAXN]; int w[MAXN]; int num[MAXN]; int cnt, ans; void addedge( int from, int to ) { edge[cnt].to = to; edge[cnt].nxt = head[from]; head[from] = cnt++; } int dfs( int u ) { if(num[u]) return num[u]; num[u] = 1; for(int i = head[u]; i != -1; i = edge[i].nxt) { int v = edge[i].to; num[u]+=dfs( v ); } return num[u]; } int main() { int n; while(scanf( "%d", &n ) == 1) { cnt = 0; memset( num, 0, sizeof num ); memset( head, -1, sizeof head ); for(int i = 1; i <= n; i++) scanf( "%d", &w[i] ); for(int i = 0; i < n - 1; i++) { int u, v; scanf( "%d%d", &u, &v ); if(w[u] < w[v]) addedge( u, v ); else addedge( v, u ); } ans = 0; for(int i = 1; i <= n; i++) ans = max( ans, dfs( i ) ); cout << ans << endl; } return 0; }
嗯就是这样!
版权声明:本文为博主原创文章,未经博主允许不得转载。