[POI2014]HOT-Hotels
阿新 • • 發佈:2018-08-23
ret math names www || play 原理 但是 dcb
題目
因為三個點肯定會有一個中轉點,然後從中將一棵無根樹轉成有根數,然後再通過乘法原理(c2表示兩兩的乘積,若有第三個數就可以變成3數相乘,就可以乘法原理了)
為什麽要搜索每顆子樹而不從從自己的根開始搜了
以為這樣就有可能不是中轉點了
所以這樣的話時間復雜的為O(N^2),但是可以使用長鏈剖分優化為O(N),雖然我不知道怎麽用,沒有學過
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespaceView Codestd; 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; longlong 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; }
[POI2014]HOT-Hotels