hdu 4705 排列组合

思路:枚举能是A,B,C在一条简单路径上的中点。 计算多少个几何能满足。在用总数减去

#pragma comment(linker, "/STACK:16777216")
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Maxn 200010
#define Maxm 300010
#define LL __int64
#define Abs(x) ((x)>0?(x):(-x))
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
#define inf 0x7fffffff
#define Mod 1000000007
using namespace std;
LL num[Maxn];
LL snum[Maxn],vi[Maxn];
vector<LL> son[Maxn];
vector<int> head[Maxn];
void dfs(int u)
{
    int i,v,sz;
    vi[u]=1;
    snum[u]=1;
    sz=head[u].size();
    for(i=0;i<sz;i++){
        v=head[u][i];
        if(vi[v]) continue;
        dfs(v);
        snum[u]+=snum[v];
        son[u].push_back(snum[v]);
    }
}
void predfs(int u,LL sum)
{
    int i,v,sz;
    vi[u]=1;
    if(sum)
        son[u].push_back(sum);
    sz=head[u].size();
    for(i=0;i<sz;i++){
        v=head[u][i];
        if(vi[v]) continue;
        predfs(v,sum+snum[u]-snum[v]);
    }
}
int main()
{
    int i,j,u,v;
    LL n;
    while(scanf("%I64d",&n)!=EOF)
    {
        memset(snum,0,sizeof(snum));
        memset(vi,0,sizeof(vi));
        memset(num,0,sizeof(num));
        for(i=0;i<=n;i++){
            son[i].clear();
            head[i].clear();
        }
        for(i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            head[u].push_back(v);
            head[v].push_back(u);
        }
        dfs(1);
        memset(vi,0,sizeof(vi));
        predfs(1,0);
        LL ans=n*(n-1)*(n-2)/6;
        //cout<<ans<<endl;
        LL sz;
        LL sum=0;
        for(i=1;i<=n;i++){
        sz=son[i].size();
            sum=0;
            for(j=0;j<sz;j++)
            sum+=son[i][j];
            for(j=0;j<sz-1;j++)
            ans-=(son[i][j]*(sum-=son[i][j]));
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

 

 

posted @ 2013-08-23 15:36  fangguo  阅读(178)  评论(0编辑  收藏  举报