codeforces 110E Lucky Tree
Posted buerdepepeqi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces 110E Lucky Tree相关的知识,希望对你有一定的参考价值。
传送门:https://codeforces.com/contest/110/problem/E
题意:给你一颗树,节点与节点之间的边有一个边权,定义只由4和7组成的数字是幸运数字,现在要你求一共有多少条路径,使得节点u->v之间至少存在一条边为幸运数字
题解:树形dp+容斥,我们要找有多少条路径上至少存在一条幸运边,那么我们就可以找到所有的不含幸运路径的边然后用所有路径和减去不含幸运路径的边即可
1,每次输入边权的时候处理边权是否为幸运数字,如果是,那么为1,否则为0
2,dfs处理,如果边权为0,那么不含幸运数字的路径+1;
3,容斥,有t条不含幸运数字的边则一共有t*(t-1)*(t-2)种方法,因为是双向边,所以容斥第二次的时候记得*2;
代码如下:
#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; }
以上是关于codeforces 110E Lucky Tree的主要内容,如果未能解决你的问题,请参考以下文章
Lucky Numbers (easy) CodeForces - 96B
CodeForces E. Lucky Array 幸运数列