首页 > 代码库 > Codeforces 109C Lucky Tree 组合计数+dfs
Codeforces 109C Lucky Tree 组合计数+dfs
题目链接:点击打开链接
题意:
给定n个点的树,有边权。
定义lucky number:数字只有4或7组成
对于一个三元组(i, j, k)
若path(i,j) 路径上的数字存在lucky number && path(i,k) 路径上的数字存在lucky number
则三元组合法。
问有多少个合法的三元组。
( (i,j,k) != (i,k,j) )
用全集-补集。dfs出每个只由 非lucky number 构成的联通块 的点数 x 。
然后方法数就是 x*(x-1)*(x-2) + x*(x-1) * (n-x) * 2
#include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <vector> #include <map> using namespace std; #define ll long long #define N 100100 bool fix(int x){ if(x == 0)return false; while(x){ int y = x%10; if(y!=4 && y!=7)return false; x /= 10; } return true; } struct Edge{ int from, to, val, nex; }edge[N<<2]; int head[N], edgenum; void add(int u, int v, int val){ Edge E = {u, v, val, head[u]}; edge[edgenum] = E; head[u] = edgenum++; } ll dp[N]; ll dfs(int u, int fa){ dp[u] = 0; for(int i = head[u]; ~i; i = edge[i].nex){ int v = edge[i].to; if(v == fa)continue; dfs(v, u); if(edge[i].val == 0){ dp[u] += dp[v]+1; dp[v] = 0; } } } void init(){memset(head, -1, sizeof head); edgenum = 0;} int n; void solve(){ int i, j, u, v, val; init(); for(i = 1; i < n; i++) { scanf("%d %d %d",&u,&v,&val); add(u, v, val); add(v, u, val); } if(n<=2){puts("0");return ;} for(i = 0; i < edgenum; i+=2)edge[i].val = edge[i^1].val = fix(edge[i].val); ll all = (ll)n; all = all * (all-1) *(all-2); dfs(1, 1); for(i = 1; i <= n; i++) if(dp[i]){ ll ans = dp[i] +1; all -= ans * (ans-1) * (ans-2); all -= ans * (ans-1) * ((ll)n - ans) * 2LL; } cout<<all<<endl; } int main(){ while(~scanf("%d",&n)){ solve(); } return 0; }
Codeforces 109C Lucky Tree 组合计数+dfs
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。