首页 > 其他分享 >CF613D 题解

CF613D 题解

时间:2023-09-08 17:13:26浏览次数:48  
标签:int 题解 top stk fa lca CF613D rep

一、题目描述:

  给你一颗 $n$ 个点的树,有 $m$ 组询问。

  一个点如果被攻占,那么这个点就不能通行了。

  第 $i$ 次询问给出 $k_i$ 个关键点,关键点不能被攻占。

  求最少攻占多少个点可以使得关键点两两不连通。若不可能,输出 $-1$。

  数据范围:$1\le n,m\le 1\times 10^5,1\le k_i\le n,\sum_{i=1}^mk_i\le 1\times 10^5$。


 二、解题思路:

  虚树板子题。话说虚树也太明显了吧?

  唯一需要注意的是当有两个儿子都是关键时不能直接返回,因为可能还有儿子没有统计答案。

  时间复杂度 $O(nlog_2^n)$。瓶颈在于计算 $lca$。


 三、完整代码:

 1 #include<bits/stdc++.h>
 2 #define V e[i].v
 3 #define N 100010
 4 #define rep(i,l,r) for(int i=l;i<=r;i++)
 5 #define per(i,r,l) for(int i=r;i>=l;i--)
 6 using namespace std;
 7 int n,m,tot,ans,flag;
 8 int f[N],g[N],q[N],r,stk[N],top;
 9 int a[N],fa[N][20],du[N],dfn[N];
10 struct EDGE{
11     int v,nxt;
12 }e[N<<3];
13 int head[N],head2[N],cnt;
14 void add(int u,int v){
15     e[++cnt].v=v;
16     e[cnt].nxt=head[u];
17     head[u]=cnt;
18 }
19 void add2(int u,int v){
20     e[++cnt].v=v;
21     e[cnt].nxt=head2[u];
22     head2[u]=cnt;
23 }
24 bool cmp(int d1,int d2){return dfn[d1]<dfn[d2];}
25 void dfs1(int u,int ff){
26     du[u]=du[ff]+1; dfn[u]=++tot; fa[u][0]=ff;
27     for(int i=head[u];i!=-1;i=e[i].nxt) if(V!=ff) dfs1(V,u);
28 }
29 int Lca(int u,int v){
30     if(du[u]<du[v]) swap(u,v);
31     per(i,19,0) if(du[u]-(1<<i)>=du[v]) u=fa[u][i];
32     if(u==v) return u;
33     per(i,19,0) if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
34     return fa[u][0];
35 }
36 void dfs2(int u){
37     g[u]=f[u]; for(int i=head2[u];i!=-1;i=e[i].nxt){
38         dfs2(V); if(g[V]) g[u]++;
39         if(f[u]&&f[V]&&fa[V][0]==u) flag=1;
40     } if(f[u]) ans+=g[u]-1; else if(g[u]>1) ans++,g[u]=0;
41 }
42 void solve(){
43     int cc; cin>>cc; rep(i,1,cc) cin>>a[i],f[a[i]]=1;
44     sort(a+1,a+1+cc,cmp); stk[top=1]=1; r=ans=flag=0;
45     rep(i,1,cc){
46         if(a[i]==1) continue;
47         int lca=Lca(stk[top],a[i]); q[++r]=lca;
48         if(lca!=stk[top]){
49             while(dfn[lca]<dfn[stk[top-1]])
50                 add2(stk[top-1],stk[top]),top--;
51             add2(lca,stk[top]);
52             if(dfn[lca]>dfn[stk[top-1]])
53                 stk[top]=lca; else top--;
54         } stk[++top]=a[i];
55     }
56     rep(i,1,top-1) add2(stk[i],stk[i+1]);
57     dfs2(1); cout<<(flag?-1:ans)<<'\n';
58     rep(i,1,r) head2[q[i]]=-1;
59     rep(i,1,cc) head2[a[i]]=-1,f[a[i]]=0;
60 }
61 int main(){
62     ios::sync_with_stdio(false);
63     cin.tie(0);cout.tie(0);
64     cin>>n; rep(i,1,n) head[i]=head2[i]=-1;
65     rep(i,1,n-1){
66         int u,v; cin>>u>>v;
67         add(u,v); add(v,u);
68     }
69     dfs1(1,0); rep(i,1,19) rep(j,1,n)
70         fa[j][i]=fa[fa[j][i-1]][i-1];
71     cin>>m; rep(i,1,m) solve();
72     return 0;
73 }

四、写题心得:

  这几天一边考试一边发现了好多遗漏的知识点,虚树是其中之一:

  $1、其实虚树真的很板,只需要建树和暴力\ dp\ 就行了。=> Exp++!$

  $2、dfs\ 的时候不要\ dp\ 到一半就贸然返回,可能还有没统计到的儿子节点。=> Exp++!$

标签:int,题解,top,stk,fa,lca,CF613D,rep
From: https://www.cnblogs.com/yhy-trh/p/CF613D.html

相关文章

  • 9月杂题题解
    arc124_e一种方案的权值为\(\prod\limits_{1\leqi\leqn}b_i\),考虑其组合意义,就是每个人在自己最终的球中选一个。可以发现要么拿自己原来的球,要么拿上一个人传来的球。定义状态:\(f(i,0)\)为第\(i\)个人拿自己的球,考虑前\(i-1\)个人的答案。\(f(i,1)\)为第\(i\)个......
  • nvm有下载版本,切换版本成功,node -v还是切换前的版本问题解决
    是因为在下载nvm之前,电脑中的node版本已经存在了,所以需要将之前的node版本全部清楚干净!卸载node之前请node-v查看一下现在的版本,记住这个版本,切记切记!!!!!控制面板中卸载node.;卸载已安装过的NVM;没装过NVM的就仅仅卸载node去环境变量里面看一下有没有跟nvm和node相关的东西了,有的话全......
  • 【题解】CF1854A2 Dual (Hard Version)
    你考虑我们A1只需要通过自加凑一个最大的数,然后将所有的数都变成正数,最后做一次前缀和即可。(不懂可以看看落谷题解)好,我们现在去看HardVersion的\(31\)次操作怎么分配:前缀和(全为正)/后缀和(全为负)——\(19\)次还剩下\(12\)次,不知道该怎么做。我们的目标便变......
  • 题解 CF1787G【Colorful Tree Again】
    problem贼眉鼠眼有一棵\(N\)个节点的树,这棵树很特殊,每条边都有边权和颜色。果宝特攻会不定时来进攻贼眉鼠眼。具体地,在前\(Q\)个时刻,在每个时刻,会发生以下两个事件之一:果宝特攻摧毁了树上的一个节点\(u\)。贼眉鼠眼修复了树上的一个节点\(u\)。定义一条简单路径......
  • 国标GB28181视频监控EasyGBS接入大量通道时,创建角色接口未响应的问题解决方法
    EasyGBS是一款基于国标GB28181协议的视频云服务平台。它支持多路设备同时接入,并能将视频流以RTSP、RTMP、FLV、HLS、WebRTC等格式分发到多个平台和终端。该平台提供了视频监控直播、云端录像、云存储、检索回放、智能告警、语音对讲、平台级联等功能。在视频能力方面,GB28181视频监......
  • CF868E Policeman and a Tree 题解
    Description.树上警察抓小偷。一名警察速度为\(1\),多名小偷速度为\(+\infty\),问多长时间抓到。树点数\(\le50\)Solution.首先不可能抓不到。其次步数不可能超过\(2500\)(每抓完一个小偷走一遍全图)。这启发我们可以直接暴搜每一步,并记忆化。如果状态设为当前在\(x\),那......
  • 【题解】《PTA-Python程序设计》题目集分享
    第1章-1从键盘输入两个数,求它们的和并输出(30分)本题目要求读入2个整数A和B,然后输出它们的和。输入格式:在一行中给出一个被加数在另一行中给出一个加数输出格式:在一行中输出和值。输入样例:在这里给出一组输入。例如:18-48输出样例:在这里给出相应的输出。例如:......
  • 题解 P8165 [eJOI2021] AddK
    不知道为什么这道题还没有题解。Solution对于操作\(1\),由于\(K\le10\),直接暴力单点修改即可。而操作\(2\)的询问,不难发现,最后结果的呈现形式是\[1\timesA_l+2\timesA_{l+1}+3\timesA_{l+2}+...+3\timesA_{r-2}+2\timesA_{r-1}+1\timesA_r\]其中中间可能有一段系数......
  • SP8177 题解
    2023-09-0111:29:13solution题意:每次询问\([l,r]\)内有多少个数满足可以被所有非\(0\)数位整除。思路看到这个数据范围和题目描述,显然是数位dp。因为\(1\sim9\)的最小公倍数是\(2520\),并且\(2520\)是其他所有\(1\sim9\)子集的最小公倍数的倍数,所以我们只需要......
  • CF402D 题解
    2023-09-0418:42:46solution不难想到我们要先记录一下每一位的前缀\(\gcd\),我们发现我们选择一位的前缀\(\gcd\)除掉以后,前缀\(\gcd\)会变为\(1\)并且会导致这位之后的\(\gcd\)全部为\(1\)。所以每一位只能选择一次,并且我们从后往前扫肯定比从前往后扫要更优。我们......