多条路径最多点权覆

Posted gcfer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多条路径最多点权覆相关的知识,希望对你有一定的参考价值。

见题:

技术图片

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

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

考虑那对于所有的叶节点来说,这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)时要大胆猜测结论,同时也要大胆外推,加以验证。

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

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

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

以上是关于多条路径最多点权覆的主要内容,如果未能解决你的问题,请参考以下文章

百度地图API——多点路径连线问题

双向多点路由重分布--如何防止路由环路以及次优路径

1018 Public Bike Management (30分)

[FJOI2014]最短路径树问题

基于JGraphT实现的路径探寻

[FJOI2014]最短路径树问题