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;

}

 

 

你可能感兴趣的:(HDU)