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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了刷题总结——拆网线(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<<"\n";
    else cout<<cnt+(K-keep)<<"\n";
  }
  return 0;
}

 

以上是关于刷题总结——拆网线(noip模拟 贪心)的主要内容,如果未能解决你的问题,请参考以下文章

刷题总结——做运动(NOIP模拟)

noip模拟赛 写代码

NOIP2017赛前模拟11月2日总结

NOIP2016提高A组模拟10.15总结

NOIP真题汇总

NOIP2017赛前模拟11月6日—7日总结