您的位置:首页 > 其它

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

2013-08-22 17:02 309 查看
#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 100011
const 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:
3
1 2
2 3
6
1 2
2 4
2 5
1 3
3 6
Output:
0
3
    方法:找到符合要求的三个点的方案数ans,答案就是C(n,3)-ans;
        枚举所有结点,以这个结点为中符合点的所有方案数和就是ans
    对于一个结点,在一棵子树上找一个点做左符合点,则其余子树上的点都右符合点。
    举例来说,一个点有三个子树,子树结点数分别为1,2,3,则符合要求的组合有(1*5+2*4+3*3)/2(会重复一次)
    
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: