您的位置:首页 > 其它

Hdu 4705 Y -- 树形

2013-09-30 10:35 393 查看
题目链接: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+5
bool vis
;
vector<int>r
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: