现在的位置: 首页 > 综合 > 正文

hdu 4705 (树形DP)

2018年12月27日 ⁄ 综合 ⁄ 共 973字 ⁄ 字号 评论关闭

给一棵树求有多少三个点之间没有简单路径,简单路径就是不走重复的点,小boss给我说了想法之后,写出来错了,不是自己想出来的方法还是有点不熟,就画图自己找,给的想法大方向上已经对了,总共有C(n,3)种组合,只要求出有简单路径的组合数就ok了,任意一点u为中间点,在当前求得的儿子son中选一个,u,剩下所有的节点n-temp-1(temp为已经求出的u的儿子个数,儿子跟儿子间不能重复运算)中选一个,可以组成有son*(n-temp-1)种组合,




#pragma comment(linker, "/STACK:1024000000,1024000000")    
#include<stdio.h>
#include<string.h>
int vis[100010],head[100010],num,n;
__int64 ans;
struct edge
{
    int st,ed,next;
}e[200010];
void addedge(int x,int y)
{
    e[num].st=x;e[num].ed=y;e[num].next=head[x];head[x]=num++;
    e[num].st=y;e[num].ed=x;e[num].next=head[y];head[y]=num++;
}
int dfs(int u)
{
	int i,v,temp=0,f;
    vis[u]=1;   
    for(i=head[u];i!=-1;i=e[i].next)
    {
        v=e[i].ed;
        if(vis[v]==1)continue;
        f=dfs(v);//当前分支儿子的个数
		temp+=f;//已经求出的儿子个数
		ans+=(__int64)(n-temp-1)*(__int64)f;//组合数
    }
    return temp+1;
}
int main()
{
    int x,y,i;
    __int64 sum,a;
    while(scanf("%d",&n)!=-1)
    {
        memset(head,-1,sizeof(head));
        num=0;ans=0;
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            addedge(x,y);
        }
        memset(vis,0,sizeof(vis));
        dfs(1);
        a=n;
        sum=a*(a-1)*(a-2)/6;
        printf("%I64d\n",sum-ans);
    }
    return 0;
}

抱歉!评论已关闭.