题意:给出一个n个节点的树形图,统计{A,B,C}的数量,其中ABC分别是树上三个不同的节点,并且这三个节点不能被一条路径覆盖
分析:对于下图
进行dfs深搜统计,num[u]统计回溯到当前节点u,并以u为根节点的子树节点个数,当回溯点到<2,4>不存在,当回溯到<2,5>时可以从{4}中和{5}中分别选择一个然后在选择4到5路径之外的其他任意一点此时ans+=(num[2]-1)*num[5]*(8-num[2]-num[5])=5;当回溯到<2,6>的时候,num[2]={4,5,2};num[6]={6};然后分别从这两个集合中分别选一个元素然后再之外选择一个ans+=(num[2]-1)*num[6]*(8-num[2]-num[6])=5+2*1*4.......最后的ans=18,这种统计方法不会有重复的数据;
#pragma comment(linker, "/STACK:1024000000,1024000000") #include"stdio.h" #include"string.h" #include"stdlib.h" #include"queue" #include"algorithm" #include"string.h" #include"string" #include"math.h" #include"vector" #include"stack" #include"map" #define eps 1e-4 #define inf 10000000 #define M 100009 #define PI acos(-1.0) using namespace std; struct node { int u,v,next; }edge[M*2]; int t,head[M],degree[M]; __int64 ans,num[M],n; void init() { t=0; memset(head,-1,sizeof(head)); } void add(int u,int v) { edge[t].u=u; edge[t].v=v; edge[t].next=head[u]; head[u]=t++; } void dfs(int u,int f) { num[u]=1; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].v; if(v==f)continue; dfs(v,u); ans+=(num[u]-1)*num[v]*(n-num[u]-num[v]); num[u]+=num[v]; } } int main() { int i,a,b; while(scanf("%I64d",&n)!=-1) { init(); for(i=1;i<n;i++) { scanf("%d%d",&a,&b); add(a,b); add(b,a); } ans=0; dfs(1,-1); printf("%I64d ",ans); } }