zoukankan      html  css  js  c++  java
  • 题解 CF109C 【Lucky Tree】

    思路:

    (quad)树形(DP +) 容斥 , (f[x]) 表示以 (x) 为根的子树中有几个点到 (x) 的路径包含幸运边, (g[x]) 表示除了 (x) 的子树外有几个点到 (x) 的路径包含幸运边,最后统计答案就是 (ans=sum_{i=1}^n) ((f[i] imes (f[i]-1)+g[i] imes (g[i]-1)+2 imes f[i] imes g[i])),数组 (f)(g) 的转移也很简单,当 (y)(x)的儿子时,若 (x)(y) 的连边为幸运边,那么 (f[x]+=size[y])(y) 的子树(包括 (y))到 (x) 的路径都包含幸运边,否则 (f[x]+=f[y])(g) 的转移也类似,如果x和y的连边是幸运边,那么 (g[y]=(n-size[y])) ,否则 (g[y]=g[x]+f[x]-f[y]) ,两遍 (dfs) 即可完成的操作,一遍自下而上,一遍自上而下,时间复杂度为 (O(3n))

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define re register int
    #define int long long
    #define LL long long
    #define il inline
    #define next nee
    #define inf 1e18
    il int read()
    {
      int x=0,f=1;char ch=getchar();
      while(!isdigit(ch)&&ch!='-')ch=getchar();
      if(ch=='-')f=-1,ch=getchar();
      while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
      return x*f;
    }
    il void print(int x)
    {
      if(x<0)putchar('-'),x=-x;
      if(x/10)print(x/10);
      putchar(x%10+'0');
    }
    const int N=1e5+5;
    int n,m,next[N<<1],go[N<<1],head[N],tot,father[N],size[N],f[N],g[N],ans;
    bool s[N<<1];
    il bool check(int x)//判断是否是幸运数字
    {
      while(x)
        {
          if(x%10!=7&&x%10!=4)return 0;
          x/=10;
        }
      return 1;
    }
    il void Add(int x,int y,bool z)
    {next[++tot]=head[x];head[x]=tot;go[tot]=y;s[tot]=z;}
    il void dfs1(int x,int fa,bool z)//第一遍dfs,处理f数组
    {
      father[x]=fa;size[x]=1;
      for(re i=head[x],y;i,y=go[i];i=next[i])
        {
          if(y==fa)continue;
          dfs1(y,x,s[i]);
          size[x]+=size[y];
          if(s[i])f[x]+=size[y];
          else f[x]+=f[y];
        }
    }
    il void dfs2(int x)//第二遍dfs,处理g数组
    {
      for(re i=head[x],y;i,y=go[i];i=next[i])
        {
          if(y==father[x])continue;
          if(s[i])g[y]=n-size[y];
          else g[y]=g[x]+f[x]-f[y];
          dfs2(y);
        }
    }
    signed main()
    {
      n=read();
      for(re i=1;i<n;i++)
        {re x=read(),y=read(),z=check(read());Add(x,y,z);Add(y,x,z);}
      dfs1(1,0,0);dfs2(1);
      for(re i=1;i<=n;i++)
        ans+=f[i]*(f[i]-1)+g[i]*(g[i]-1)+f[i]*g[i]*2;//简单的组合数学计算方案
      print(ans);
      return 0;
    }
    
  • 相关阅读:
    《Head First》 MVC运用的设计模式
    unity工具 Animator的使用
    服务器搭建 如果搭建KBE开源服务器
    unity 实战图片挖洞Mask(转载)
    unity博客 推荐(不断补充)
    unity实战 UGUI英雄联盟英雄头顶分段式血条
    unity组成 ToLua
    unity实战 UGUI Text 间距和ContentSizeFitter组件的适配
    unity工具 推荐(不断补充)
    各种单例模式的对比分析
  • 原文地址:https://www.cnblogs.com/FarkasW/p/14027455.html
Copyright © 2011-2022 走看看