其他分享
首页 > 其他分享> > CF #805(div3) G1. Passable Paths (easy version) 找规律+树上模拟~

CF #805(div3) G1. Passable Paths (easy version) 找规律+树上模拟~

作者:互联网

思路来自实验室一个work hard的学长~

题意是说有一个点集,在树上,能否一笔画把这些点集走一遍

easy版本因为q在[1,5]之前,范围比较小,可以暴力

考虑什么情况下不能一笔画~

如果对于一个点,它的分支有父亲fa、若干个儿子son

设想如果很多个分支上都有点集,显然没法一笔画走过去

当且仅当有点集的分支小于等于两个时,才能满足条件;

一个会被卡的点是怎么判断往上走,父亲那边有没有点集?

在dfs的过程中我们多记一个tot[u],tot[u]表示以u为根的子树所包含的点的数目(包括u自己);

如果k-tot[u]>0,说明除了在子树外必然还有点,那往上走这个分支也有贡献~

#大概是以上这样子

#include<bits/stdc++.h>
using namespace std;
struct lys{
    int from,to,nex;
}e[500007];
int n,q,k,flag,cnt=0,keyp[500007],head[500007],size[500007],tot[500007];
void add(int from,int to)
{
    cnt++;
    e[cnt].to=to;e[cnt].from=from;
    e[cnt].nex=head[from];head[from]=cnt;
}
void dfs(int u,int fa)
{
    if(keyp[u]) tot[u]++;
    
    for(int i=head[u];i;i=e[i].nex)
    {
        int to=e[i].to;
        if(to==fa) continue;
        dfs(to,u);
        if(size[to]||keyp[to]){
            size[u]++;
        }
        tot[u]+=tot[to];
    }
    int delta;
    if(k-tot[u]) delta=1;
    else delta=0;

    if(delta+size[u]>2) flag=0;
//    cout<<u<<" "<<size[u]<<" "<<tot[u]<<endl;
}
int main()
{
    //freopen("lys.in","r",stdin);
    
   cin>>n;
   for(int i=1;i<n;i++)
   {
       int a,b;
       cin>>a>>b;add(a,b);add(b,a);
   }
   cin>>q;
   for(int i=1;i<=q;i++)
   {
       memset(size,0,sizeof(size));
       memset(keyp,0,sizeof(keyp));
       memset(tot,0,sizeof(tot));
       flag=1;  
         
         cin>>k;
         for(int j=1;j<=k;j++)
         {int p;
         cin>>p;
         keyp[p]=1;     
      }
      dfs(1,0);
      if(flag==1) {
          cout<<"YES"<<endl;
      }
      else {
          cout<<"NO"<<endl;
      }
   }
}

 

标签:Paths,cnt,G1,int,CF,tot,dfs,500007,size
来源: https://www.cnblogs.com/liyishui2003/p/16467759.html