zoukankan      html  css  js  c++  java
  • codeforces 110E Lucky Tree

    传送门:https://codeforces.com/contest/110/problem/E

    题意:给你一颗树,节点与节点之间的边有一个边权,定义只由4和7组成的数字是幸运数字,现在要你求一共有多少条路径,使得节点u->v之间至少存在一条边为幸运数字

    题解:树形dp+容斥,我们要找有多少条路径上至少存在一条幸运边,那么我们就可以找到所有的不含幸运路径的边然后用所有路径和减去不含幸运路径的边即可

       1,每次输入边权的时候处理边权是否为幸运数字,如果是,那么为1,否则为0

       2,dfs处理,如果边权为0,那么不含幸运数字的路径+1;

       3,容斥,因为是一个三元组,我们先从n个点选一个点,再从n-1个点选一个点,再从n-2个点选一个点,那么一共有n*(n-1)*(n-2)种选取三元组的方法。

          如果这个第i个节点存在没有幸运边的情况,那么就从这些边中选3条,方法数是tmp*(tmp-1)*(tmp-2),这是i->j,i->k都没有幸运数的情况

          另外一种是i->j没有幸运数但i->k有幸运数,或者i->j有幸运数,但i->k没有幸运数的情况为2*tmp*(tmp-1)*(n-tmp)

    代码如下:

    #include <map>
    #include <set>
    #include <cmath>
    #include <ctime>
    #include <stack>
    #include <queue>
    #include <cstdio>
    #include <cctype>
    #include <bitset>
    #include <string>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    #define fuck(x) cout<<"["<<x<<"]";
    #define FIN freopen("input.txt","r",stdin);
    #define FOUT freopen("output.txt","w+",stdout);
    //#pragma comment(linker, "/STACK:102400000,102400000")
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> PII;
    const int maxn = 1e5+5;
    const int INF = 0x3f3f3f3f;
    const int MOD = 1e9+7;
    struct node{
        int v,next;
        LL w;
    }edge[maxn<<2];
    int head[maxn],tot;
    LL dp[maxn];
    void add(int u,int v,int w){
        edge[tot].v=v;
        edge[tot].w=w;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    void dfs(int u,int fa){
        dp[u]=0;
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            if(v==fa) continue;
            dfs(v,u);
            if(edge[i].w==0){
                dp[u]+=dp[v]+1;
                dp[v]=0;
            }
        }
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        FIN
    #endif
        int u,v;
        LL n,w,f;
        tot=0;
        memset(head,-1,sizeof(head));
        scanf("%lld",&n);
        for(int i=1;i<n;i++){
            scanf("%d%d%lld",&u,&v,&w);
            f=1;
            while(w){
                if(w%10!=4&&w%10!=7) f=0;
                w/=10;
            }
            add(u,v,f);
            add(v,u,f);
        }
        if(n<=2){
            printf("0
    ");
            return 0;
        }
        dfs(1,1);
        LL ans=(LL)n*(n-1)*(n-2);
        for(int i=1;i<=n;i++){
            if(dp[i]){
                LL tmp=dp[i]+1;
                ans-=tmp*(tmp-1)*(tmp-2);
                ans-=tmp*(tmp-1)*((LL)n-tmp)*2;
            }
        }
        cout<<ans<<endl;
    
    }
    View Code
    每一个不曾刷题的日子 都是对生命的辜负 从弱小到强大,需要一段时间的沉淀,就是现在了 ~buerdepepeqi
  • 相关阅读:
    Git代码行数统计命令
    JPA访问数据库的几种方式
    爱码小士丨代码一敲十年,收入虽高前途摇摆
    “肉瘾”女孩从软件测试工程师到主管的成长感悟
    华为测试大牛Python+Django接口自动化怎么写的?
    携程大牛的单元测试是怎么样写的?
    Jmeter参数的AES加密使用
    弄啥嘞?热爱你的Bug
    “进腾讯工作一个月,我想辞职了”
    我在华为,软件测试人员在工作中如何运用Linux?
  • 原文地址:https://www.cnblogs.com/buerdepepeqi/p/9515185.html
Copyright © 2011-2022 走看看