hdu 4705 Y/杭电2013年多校第十场1010 组合

来源:互联网 发布:php沐辰的博客 编辑:程序博客网 时间:2024/05/18 18:53
#pragma comment(linker, "/STACK:16777216")#include <cstdio>#include <cstring>#include <cmath>#include <vector>#include <algorithm>#include <iostream>using namespace std;#define LL __int64#define maxn 100011const int mod=1e9+7;vector<int>e[maxn];int c[maxn],d[maxn];int dfs(int pre,int u)//以1为根结点{    c[u]=1;//记录点的子树结点数和+1    d[u]=pre;//记录父节点    int i,v;    if(e[u].size()==1&&e[u][0]==pre)        return c[u];    for(i=0;i<e[u].size();i++)    {        v=e[u][i];        if(v==pre)continue;        c[u]+=dfs(u,v);    }    return c[u];}int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        int i,j,k,a,b;        for(i=1;i<=n;i++)            e[i].clear();        for(i=1;i<n;i++)        {            scanf("%d%d",&a,&b);            e[a].push_back(b);            e[b].push_back(a);        }        dfs(-1,1);        /*for(i=1;i<=n;i++)            cout<<c[i]<<" ";        cout<<endl;*/        int v,u;        LL ans=0,s;        for(i=1;i<=n;i++)        {            s=0;            if(e[i].size()==1)continue;            for(j=0;j<e[i].size();j++)            {                v=e[i][j];                if(v==d[i])a=n-c[i];                else a=c[v];                b=n-a-1; //a为左符合点数,b为右符合点数                s+=(LL)a*b;            }            ans+=s/2;        }        //cout<<ans<<endl;        ans=(LL)n*(n-1)*(n-2)/6-ans;        printf("%I64d\n",ans);    }    return 0;}/*样例:Input:31 22 361 22 42 51 33 6Output:03    方法:找到符合要求的三个点的方案数ans,答案就是C(n,3)-ans;        枚举所有结点,以这个结点为中符合点的所有方案数和就是ans    对于一个结点,在一棵子树上找一个点做左符合点,则其余子树上的点都右符合点。    举例来说,一个点有三个子树,子树结点数分别为1,2,3,则符合要求的组合有(1*5+2*4+3*3)/2(会重复一次)    */

原创粉丝点击