bzoj 3522: [Poi2014]Hotel dfs

来源:互联网 发布:ecjia到家源码下载 编辑:程序博客网 时间:2024/05/29 06:32

题意

有一个树形结构的宾馆,n个房间,n-1条无向边,每条边的长度相同,任意两个房间可以相互到达。吉丽要给他的三个妹子各开(一个)房(间)。三个妹子住的房间要互不相同(否则要打起来了),为了让吉丽满意,你需要让三个房间两两距离相同。
有多少种方案能让吉丽满意?
n≤5000

分析

一开始yy了一种dfs两边的方法,每个点要开一个大小为n的桶,结果发现被卡空间了。。。
其实可以对每个点为根的情况做一次,然后遍历其所有子树,开个桶记录每个深度出现的次数然后排列组合随便算即可。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;const int N=5005;int cnt,last[N],t[N],dep[N],mxd[N],n,t1[N];LL at[N],ans;struct edge{int to,next;}e[N*2];void addedge(int u,int v){    e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;    e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;}void dfs(int x,int fa,int dep){    t1[dep]++;    for (int i=last[x];i;i=e[i].next) if (e[i].to!=fa) dfs(e[i].to,x,dep+1);}int main(){    scanf("%d",&n);    for (int i=1;i<n;i++)    {        int x,y;        scanf("%d%d",&x,&y);        addedge(x,y);    }    for (int i=1;i<=n;i++)    {        memset(t,0,sizeof(t));        memset(at,0,sizeof(at));        for (int j=last[i];j;j=e[j].next)        {            dfs(e[j].to,i,2);            for (int k=1;k<=n;k++)                if (t1[k])                {                    ans+=(LL)at[k]*t1[k];                    at[k]+=(LL)t1[k]*t[k];                    t[k]+=t1[k];                    t1[k]=0;                }        }    }    printf("%lld",ans);    return 0;}
0 0