• 刷题总结——拆网线(noip模拟 贪心)


    题目:

      给定一颗树··在保证有k个点与其它点连接的情况下问最少保留多少条边····

      树的节点树n和k均小于100000;

    题解:

      很容易看出来我们要尽量保留那种一条边连两个节点的情况····

      然后考试的时候我以为这就完了··xjb贪完心后错了一大半····

      下次一定要写对拍了,艹

      贪心的时候我们要沿着叶子节点来贪心···这样就能保证正确性了···证明的话就不细说了··不信的话打个对拍看看···

    代码:

      

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<string>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5;
    int T,n,K,fst[N],nxt[N*2],go[N*2],tot,cnt,keep;
    bool del[N];
    inline int R()
    {
      char c;int f=0;
      for(c=getchar();c<'0'||c>'9';c=getchar());
      for(;c<='9'&&c>='0';c=getchar())  f=(f<<3)+(f<<1)+c-'0';
      return f;
    }
    inline void comb(int a,int b)
    {
      nxt[++tot]=fst[a],fst[a]=tot,go[tot]=b;
      nxt[++tot]=fst[b],fst[b]=tot,go[tot]=a;
    }
    inline void pre()
    {
      cnt=tot=keep=0;
      memset(fst,0,sizeof(fst));
      memset(del,false,sizeof(del));
    }
    inline void dfs(int u,int fa)
    {
      for(int e=fst[u];e;e=nxt[e])
      {
        int v=go[e];if(v==fa)  continue;
        dfs(v,u);
        if(!del[v]&&!del[u])
        {
          if(keep<K)
          {
            keep+=2;cnt++;
            del[v]=del[u]=true;
          }
        }
      }
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      T=R();int a;  
      while(T--)  
      {
        n=R(),K=R();pre();
        for(int i=1;i<n;i++)  a=R(),comb(i+1,a);
        dfs(1,0);
        if(keep>=K)  cout<<cnt<<"
    ";
        else cout<<cnt+(K-keep)<<"
    ";
      }
      return 0;
    }
  • 相关阅读:
    水木→函数式编程语言→lisp是不是主要用来编网站的?
    OpenMP 维基百科,自由的百科全书
    一个实际的Lisp项目开发心得 albert_lee的产品技术空间 博客频道 CSDN.NET
    ...
    OpenMPI
    Debian下安装NetBeans
    Linux Socket学习(十七)
    Linux Socket学习(十四)
    Debian下安装Latex
    Debian下安装virtualbox
  • 原文地址:https://www.cnblogs.com/AseanA/p/7718675.html
Copyright © 2020-2023  润新知