因为三个点肯定会有一个中转点,然后从中将一棵无根树转成有根数,然后再通过乘法原理(c2表示两两的乘积,若有第三个数就可以变成3数相乘,就可以乘法原理了)
为什么要搜索每颗子树而不从从自己的根开始搜了
以为这样就有可能不是中转点了
所以这样的话时间复杂的为O(N^2),但是可以使用长链剖分优化为O(N),虽然我不知道怎么用,没有学过
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; inline long long read() { long long f=1,ans=0;char c; while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-‘0‘;c=getchar();} return f*ans; } long long c1[10001],c2[10001],n; struct node{ long long u,v,nex; }x[10001]; long long cnt=0; long long ans[10001],head[5001],maxn,sum; void add(long long u,long long v) { x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++; } void dfs(long long pos,long long fath,long long anss) { maxn=max(maxn,anss); ans[anss]++; for(long long i=head[pos];i!=-1;i=x[i].nex) { if(x[i].v!=fath) dfs(x[i].v,pos,anss+1); } } int main() { memset(head,-1,sizeof(head)); n=read(); for(long long i=1;i<n;i++) { long long u=read(),v=read(); add(u,v),add(v,u); // cout<<i<<endl; } for(long long i=1;i<=n;i++) { memset(c1,0,sizeof(c1)); memset(c2,0,sizeof(c2)); for(long long j=head[i];j!=-1;j=x[j].nex) { maxn=0; dfs(x[j].v,i,1); for(long long k=1;k<=maxn;k++) { sum+=ans[k]*c2[k]; c2[k]+=c1[k]*ans[k]; c1[k]+=ans[k]; ans[k]=0; } } } cout<<sum; }
原文:https://www.cnblogs.com/si-rui-yang/p/9520876.html