Hdu 4705 Y -- 树形

来源:互联网 发布:vscode路径插件 编辑:程序博客网 时间:2024/04/30 23:17

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4705

题意:给一棵树,让你找到一个三个节点的集合,这三个节点不能在一条简单的路上(要有支路,或者说有交点,语文表达不好。。。)求一共有几种可能。

思路:用全部可能值 C( N , 3 ) 减去每一条路上的三元集合数ans。

具体做法是:

1>从一个结点a出发,找它所有的子节点的儿子总数had,在每一个子节点的儿子数son。每找到一个子节点,had加上新找到的son数,一条路上可找到的三元集合数就多了(n-had-1)*son个。表示此子节点xi,子节点的儿子xxi和xi的其他未找到的儿子中任选一个xii 组成的三元集合。

2>递归求解。

 

 

#pragma comment(linker, "/STACK:16777216")#include<cstdio>#include<vector>#include<string.h>#include<iostream>using namespace std;#define ll __int64#define N 100000+5bool vis[N];vector<int>r[N];ll n,ans,all;ll dfs(int u){    int v;    ll had = 0,son;    vis[u]=1;       for(unsigned int i = 0;i < r[u].size();i++)    {        v=r[u][i];        if(!vis[v])        {            son = dfs(v);            had += son;            ans += (n-had-1)*son;            //n-已经算过的儿子的数目-u本身==u的其他未算过的儿子数,            //再乘上son,当下结点一枝的儿子数        }    }    return had+1;}void init(){    memset(vis,0,sizeof(vis));    for (int i = 0; i < N; i++)    {        r[i].clear();    }    ans = 0;    all = n*(n-1)*(n-2)/6;//C(n,3)}int main(){    int u,v;    while(cin>>n){        init();        for(int i = 1;i<n;i++)        {            cin>>u>>v;            r[u].push_back(v);            r[v].push_back(u);        }        dfs(1);        cout<<all-ans<<endl;    }    return 0;}

原创粉丝点击