HDU 4705 Y (树形DP)

来源:互联网 发布:js 日期转时间戳 编辑:程序博客网 时间:2024/05/18 03:03

思路:反面考虑,用总的方案数减去A,B,C三点在同一路径上的方案数。于是我们可以确定中间点B,在当前以B为根求得的son中任选一个,在剩下的节点n-tmp-1(tmp为已经求得的B的儿子的个数)中任选一个,产生tmp*(n-tmp-1)中组合。

//#pragma comment(linker, "/STACK:102400000,102400000")#pragma comment(linker, "/STACK:16777216")#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <cmath>#include <queue>using namespace std;typedef long long LL;const int INF =1000000000;const int M = 10000010;const int MAXN = 100100;struct Edge{    int v,next;} edge[MAXN*4];int NE;long long n;int head[MAXN];void Insert(int u,int v){    edge[NE].v=v;    edge[NE].next=head[u];    head[u]=NE++;}bool mark[MAXN];LL sum,ans;int dfs(int u){    mark[u]=true;    int son,tmp=0;    for(int i=head[u]; ~i; i=edge[i].next)    {        int v=edge[i].v;        if(mark[v])            continue;        son=dfs(v);//当前分支儿子的个数        tmp+=son;//已经求出的儿子的个数        ans+=(LL)(n-1-tmp)*son;    }    return tmp+1;}int main(){    int u,v;    while(~scanf("%I64d",&n))    {        NE=0;        memset(head,-1,sizeof(head));        for(int i=1; i<n; i++)        {            scanf("%d%d",&u,&v);            Insert(u,v);            Insert(v,u);        }        memset(mark,false,sizeof(mark));        ans=0;        dfs(1);        sum=n*(n-1)*(n-2)/6;        printf("%I64d\n",sum-ans);    }    return 0;}



0 0
原创粉丝点击