zoukankan      html  css  js  c++  java
  • [agc004D]Teleporter

    Description 

    传送门

     Solution

    依题意我们可以知道,以2-n为出发点的边和1号节点会构成一课树(不然2-n号节点无法都达到首都)。

    为了让2-n号节点中,离1号节点的距离<k的能够使到1号点到路径长为k(>k的先不讨论),我们需要1号节点的边指向自己。(否则1号节点会和某些点组成一个环,由于环的大小>1,距离<k的点只能不断给路径长度加上环的大小,总是会有这样的点路径长不能等于k)

    至于>k的点,我们就考虑贪心强拆,从下往上贪心。如果当前处理到了一棵深度=k-1的子树(设子树根节点深度1)则需要把这棵子树拆出来(其实是让子树根节点出发的边指向首都),当然根节点要特判。

    其实贪心也可以从上往下。但是从下往上才能够得到最优解。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int n,k,a[100010],dep[100010],maxn[100100],ans;
    struct node{int y,nxt;
    }g[100010];int h[100010];
    void dfs(int x)
    {
        for (int i=h[x];i;i=g[i].nxt)
        if (g[i].y!=x)
        {
            dep[g[i].y]=dep[x]+1;
            dfs(g[i].y);
            maxn[x]=max(maxn[x],maxn[g[i].y]);
        }
        maxn[x]=max(maxn[x],dep[x]);
        if (x==1) return;
        if (maxn[x]-dep[x]>=k-1&&a[x]!=1||(maxn[x]-dep[x]>=k)) maxn[x]=0,ans++;
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        scanf("%d",&a[1]);
        for (int i=2;i<=n;i++) 
        {
            scanf("%d",&a[i]);    
            g[i]=node{i,h[a[i]]};h[a[i]]=i;    
        }
        ans=0;
        dfs(1);
        if (a[1]!=1) ans++;
        printf("%d",ans);
    }
  • 相关阅读:
    c++中sort等算法中比较操作的规则
    数据结构(c++)(1)-- 栈
    Problem 10: Summation of primes
    Problem 9: Special Pythagorean triplet
    Problem 7: 10001st prime
    Problem 8: Largest product in a series
    Problem 5: Smallest multiple
    Problem 6: Sum square difference
    Problem 4: Largest palindrome product
    Problem 3: Largest prime factor
  • 原文地址:https://www.cnblogs.com/coco-night/p/9493080.html
Copyright © 2011-2022 走看看