题解 CF580C 【Kefa and Park】

sukimo

2020-04-09 14:25:16

Solution

一道搜索题,思路就是从根节点开始dfs找路径的时候统计。之前被卡过几次,后来找到了错误。对于每个dfs到的节点,维护$3$个参数: $1$.当前节点编号 $2$.以当前节点结尾的连续点权为$1$的节点个数 $3$.从根节点走到当前节点的路径,最大连续点权为$1$的节点个数 三个信息都比较好维护,其中参数$2$和$3$需要互相更新(见代码,只要理解了上面三个参数的意义,代码非常好理解)。如果在半路参数$3$就大于$m$了,可以直接剪掉。我采用的判断叶节点方法是记下每个点的连边数量,如果只连了一条边且不是根节点(第二个条件很重要!!,因为可以造出两点一边的特殊数据,这时根节点也只连了一条边),就是叶节点。 上代码: ``` #include<bits/stdc++.h> using namespace std; const int MX=100005;int m,tot,in[MX],vis[MX],fir[MX],val[MX];struct STR{int next,to;}edge[MX<<1]; void add(int u,int v,int cnt){edge[cnt].to=v;edge[cnt].next=fir[u];fir[u]=cnt;} void dfs(int x,int now_cnt,int _max){ if(_max>m)return;if(!(in[x]-1)&&x-1){tot++;return;} vis[x]=1; for(int i=fir[x];i;i=edge[i].next) if(!vis[edge[i].to]){ int q=val[edge[i].to]?now_cnt+1:0;dfs(edge[i].to,q,max(_max,q)); } } int main(){ int n;scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&val[i]); for(int i=1;i<=n-1;i++){int u,v;scanf("%d%d",&u,&v);add(u,v,i);add(v,u,i+n-1);in[u]++;in[v]++;} dfs(1,val[1],val[1]);printf("%d",tot); return 0; } ```