解题报告 之 HDU5325 Crazy Bobo

18 篇文章 0 订阅
2 篇文章 0 订阅

解题报告 之 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;
}

嗯就是这样!



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值