现在的位置: 首页 > 综合 > 正文

HDUOJ 4705 2013多校第十场第10题 Y

2019年02月27日 ⁄ 综合 ⁄ 共 938字 ⁄ 字号 评论关闭

传送门

题意:一棵树,问不能再一条线上的三个点有多少种。

思路:先求出能在一条线上的三个点的种类数,然后拿C(n,3)减掉就是答案。求前面的值可以枚举中点,在此之前先dfs一边,算出所有节点的子节点个数。

吐槽:多校就这么结束了。。。。

#pragma comment(linker, "/STACK:16777216")
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n;
int fst[100005],next[200005],node[200005],en,c[100005],pre[100005];
long long int ans,cnt,s;
int dfs(int u,int p)
{
    c[u]=1;
    pre[u]=p;
    if(next[fst[u]]==-1&&node[fst[u]]==p)return c[u];
    for(int i=fst[u]; i!=-1; i=next[i])
    {
        if(node[i]==p)continue;
        c[u]+=dfs(node[i],u);
    }
    return c[u];
}
int main()
{
    int u,v;
    while(scanf("%d",&n)!=EOF)
    {
        en=0;
        memset(fst,-1,sizeof(fst));
        for(int i=1; i<n; i++)
        {
            scanf("%d%d",&u,&v);
            next[++en]=fst[u];
            fst[u]=en;
            node[en]=v;
            next[++en]=fst[v];
            fst[v]=en;
            node[en]=u;
        }
        dfs(1,-1);
        cnt=0;
        for(int i=1; i<=n; i++)
        {
            if(next[fst[i]]==-1)continue;
            s=0;
            for(int j=fst[i]; j!=-1; j=next[j])
            {
                v=node[j];
                if(pre[i]==v)s+=(1LL)*(n-c[i])*(c[i]-1);
                else s+=(1LL)*c[v]*(n-c[v]-1);
            }
            cnt+=s/2;
        }
        ans=(1LL)*n*(n-1)*(n-2)/6-cnt;
        printf("%I64d\n",ans);
    }
    return 0;
}
【上篇】
【下篇】

抱歉!评论已关闭.