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

    题意:

    给你一个n个点n条边的基环外向树(即在一棵树上加了一条边,边有方向,且加的那条边一定有个端点是1号点),每条边长度为1,让你改变若干条边使得每个结点走k步均恰好可以到达1号点,求最小要改变几次。

    $n<10^5,k<10^9$

    题解:

    本质是道简单题……但是题目描述非常鬼畜,导致我看了十分钟才看懂要干什么……

    首先显然要把1号点那条多出来的边连回自己形成自环,否则$k>1$时肯定无法实现。然后就可以直接贪心了。。。从下到上计算距离,只要最深的结点距离超过了k就操作一次并把距离重设为0,然后就。。。没了。。。

    注意如果1号点原本没有连自己答案要+1(因为自己连回自己要操作一次),很多人被这个坑了

    代码:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 using namespace std;
     6 struct edge{
     7     int v,next;
     8 }a[100001];
     9 int n,k,x,ans=0,tot=0,num[100001],head[100001],dis[100001];
    10 void add(int u,int v){
    11     a[++tot].v=v;
    12     a[tot].next=head[u];
    13     head[u]=tot;
    14 }
    15 void dfs(int u){
    16     dis[u]=1;//开始忘了这句,只有50
    17     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
    18         int v=a[tmp].v;
    19         dfs(v);
    20         dis[u]=max(dis[u],dis[v]+1);
    21     }
    22     if(dis[u]>=k&&num[u]!=1){
    23         ans++;
    24         dis[u]=0;
    25     }
    26 }
    27 int main(){
    28     memset(head,-1,sizeof(head));
    29     memset(dis,0,sizeof(dis));
    30     scanf("%d%d",&n,&k);
    31     for(int i=1;i<=n;i++){
    32         scanf("%d",&num[i]);
    33         if(i==1){
    34             if(num[i]!=1)ans++;
    35             num[1]=1;
    36         }else{
    37             add(num[i],i);
    38         }
    39     }
    40     dfs(1);
    41     printf("%d",ans);
    42     return 0;
    43 }
  • 相关阅读:
    【JS基础】数组
    【JS基础】循环
    【JS基础】DOM操作
    移动端字体
    【JQ基础】
    【JS基础】
    WebBrowser.DocumentText引发FileNotFound异常
    抽取网络信息进行数据挖掘 建立语料库
    文本分类和聚类有什么区别?
    C# 读取网页源代码
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/9494018.html
Copyright © 2011-2022 走看看