[UESTC SC T1] 最大疯子树

暂无链接

最大疯子树

【题目描述】

给定一棵n 个结点的树,结点编号为1~n,i 号结点的权重记为wi(每个点
的权值各不相同)。我们定义一个“疯子树”为:
1.是一个联通子图。
2.我们将子图内的点按照权重从小到大排序后序列为b_1,b_2,…,b_m,对于任
意的i(i

【输入格式】

数据有多组case,文件以EOF 结束,每组第一行输入一个n 表示树的节点数;
接下来一行包含n 个整数,第i 个数表示i 号结点的权重wi;接下行n-1 行,第i 行包含2 个整数ui, vi,表示ui 和vi 有一条边。

【输出格式】

对于每组case 输出一行,包含一个整数,表示包含结点最多的“疯子树”
的结点数。

【样例输入】

5
1 4 2 3 5
1 2
2 3
3 4
4 5
5
2 5 4 1 3
1 2
2 3
3 4
4 5

【样例输出】

4
4

【数据范围】

对于10%的数据有所有组的n 之和n≤20。
对于30%的数据有所有组的n 之和n≤2000。
3
对于100%的数据有所有组的n 之和n≤200000,0 < wi≤100000000,n 为正
整数。

题解

我们先看疯子树为一条链的情况:

因为满足最大疯子树的性质,所以在这条链上两端的权值均大于中间的的点的权值,如果我们按照权值和点的编号绘一个图,趋势大概如下:

可以看到大概趋势就是一个凹的形状,那么再考虑复杂点的情况:

我们可以把这个图拆成ABD,ABCD,DBCD这三条链,每条链都应该满足上面的凹形,所以这个图中的权值关系如下图所示:

那么,针对更加复杂的情况,一个疯子树可以想象成一个蜘蛛网,中心为一个权值最小的节点,把整张蜘蛛网向下“拉”。

那么我们考虑如何递推这个疯子树的大小,先考虑从小开始推,但是最后递推的值汇集到了最大的点上,我们并不能通过最大的点上得到的值得到整棵疯子树的大小。

如上图,我们即使得到了4,也并没有什么* 用,因为我们求出的是虚线中“反疯子树”的大小。

那么我们不如反过来推,从大的往小的扩散,这样汇集到最小的点上的时候,就能得出答案。

代码
#include<bits/stdc++.h>
using namespace std;
const int M=2e5+5;
struct node{
    int w,id;
};
bool operator <(node a,node b){return a.w>b.w;}
int n,val[M];
node pt[M];
vector<int>tree[M];
bool del[M];
void in()
{
    int a,b;
    for(int i=1;i<=n;++i)
    scanf("%d",&pt[i].w),pt[i].id=i;
    for(int i=1;i<n;++i)
    {
        scanf("%d%d",&a,&b);
        tree[a].push_back(b);
        tree[b].push_back(a);
    }
}
void ac()
{
    int ans=0;
    sort(pt+1,pt+1+n);
    for(int i=1;i<=n;++i)
    {
        del[pt[i].id]=1;
        for(int j=tree[pt[i].id].size()-1;j>=0;--j)
        {
            if(!del[tree[pt[i].id][j]])
            val[tree[pt[i].id][j]]+=val[pt[i].id]+1;
        }
    }
    for(int i=1;i<=n;++i)
    ans=max(ans,val[i]);
    printf("%d\n",ans+1);
    memset(val,0,sizeof(val));
    memset(pt,0,sizeof(pt));
    memset(del,0,sizeof(del));
    for(int i=1;i<=n;++i)
    tree[i].clear();
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    in(),ac();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值