码迷,mamicode.com
首页 > 其他好文 > 详细

多条路径最多点权覆

时间:2019-07-16 12:56:59      阅读:92      评论:0      收藏:0      [点我收藏+]

标签:pac   cin   mic   ima   png   mamicode   限制   clu   line   

见题:

技术图片

题目简单粗暴,真的很难想。

直接从优解的角度考虑:每条路径都是从一个叶节点到另一个叶节点的,显然这样可以经过最多的点。

考虑那对于所有的叶节点来说,这l条路径,最多覆盖l*2个点(因为每条路径最多覆盖两条叶节点),这是针对于叶节点来说的,那对于其他节点呢?

我们顺着这个思路,从叶节点向上推一层,在叶节点之上的一层,最多也覆盖l*2个点,同理,往上的每一层,对答案的贡献也都是l*2,同时加上该层的点数限制。

一层一层往上推,那不就是拓扑吗?我们可以从叶节点开始跑拓扑,记录其所在层数,最后输出答案。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010000;
int n,l,link[maxn],tot,ru[maxn],ans,deep[maxn],cnt[maxn],vis[maxn],p;
struct bian
{
    int y,next;
};
bian a[maxn*2];
inline void add(int x,int y)
{
    a[++tot].y=y;
    a[tot].next=link[x];
    link[x]=tot;
}
inline void topsort()
{
    queue<int>q;
    for(int i=1;i<=n;i++) if(ru[i]==1) {q.push(i);vis[i]=1;}
    while(!q.empty())
    {
        int x=q.front();q.pop();cnt[deep[x]]++;
        for(int i=link[x];i;i=a[i].next)
        {
            int y=a[i].y;
            if(vis[y]) continue;
            deep[y]=deep[x]+1;
            p=max(p,deep[y]);
            if(--ru[y]==1) {q.push(y);vis[y]=1;}
        }
    }
}
int main()
{
    freopen("1.in","r",stdin);
    cin>>n>>l;
    for(int i=1;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        add(x,y);add(y,x);
        ru[x]++;ru[y]++;
    } 
    topsort();
    for(int i=0;i<=p;i++) ans+=min(2*l,cnt[i]);
    cout<<ans<<endl;
    return 0;
} 

这个题启示我们,O(n)时要大胆猜测结论,同时也要大胆外推,加以验证。

其实本题的思路是直接从最有解的角度出发,考虑最优解一定有用的性质,从这些性质着手反推最优解,这种思路也是找结论时常用的思路。

那本题为什么要用拓扑呢?整体看一下本题的探索思路,我们先考虑了最优路径一定从叶节点到叶节点,之后以叶节点为一层,一步步向外推,这种一层层从已知到未知,不就是拓扑的性质!

这个题启示我们:假使遇到从叶节点出发有规律可循,可以一步一步外推至最优解,这时要合理猜测,不要忘记拓扑的力量!

多条路径最多点权覆

标签:pac   cin   mic   ima   png   mamicode   限制   clu   line   

原文地址:https://www.cnblogs.com/gcfer/p/11193912.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!