HDU 4705 Y 树形枚举
树形枚举--搜索
题目描述:
给你一棵树,要在一条简单路径上选3个不同的点构成一个集合,问能构成多少个不同的集合。
解法:
枚举所有结点,假设某个结点有n棵子树,每棵子树的结点个数分别为s1,s2,````sn.那么在选中该结点后,剩下的两个结点从子树上选,考虑顺序,则有方案数ans = s1*(sum(si) - s1) + s2*(sum(si) - s2) + ``` + sn*(sum(si) - sn),化简得ans = sum(si) ^ 2 - sum(si ^2) .实际上,另外两个点选了(1,2)和(2,1)对于集合{a,b,c}而言是一样的,所以方案数应该为ans/2。
而一个结点的子节点的总和为n-1。只要求sum(si^2)即可,由于是从某一点开始搜的,我们把这个点想成了根结点,实际上对于除这个点以外的其他点,除了按搜索顺序认为的子树外,剩下的结点是它的另一棵子树。
代码实现:
ll ans=0;
int dfs(int x)//返回该结点的某棵子树的结点个数
{
vis[x] =1;
ll sq=0;//”子树”结点个数的平方和
int tot =0;//”子树”结点个数的总和
for(int i=0; i<g[x].size(); ++i)
{
if(!vis[g[x][i]])
{
int son = dfs(g[x][i]);//子结点的个数
tot += son;
sq += (ll)son*son;
}
}
sq += (ll)(n-tot-1)*(n-tot-1);
ans += ((ll)(n-1)*(n-1) - sq)/2;
return tot+1;//当自己作为子树时,还要加上自己,所以加1.
}
另一种解法:
直接考虑顺序计数,有方案数ans =s1*(s2+s3+````+sn)+s2*(s3+s4+```sn) +```` + s[n-1]*sn. 则有设sum[i]为前i项和,则有ans = s1*(n-1-sum[1]) + s2*(n-1-sum[2]) +````+s[n-1]*(n-1-sum[n-1]) + sn *0.
代码实现:
ll ans;
int dfs(int x)
{
vis[x] =1;
int tmp=0;
for(int i=0; i<g[x].size(); ++i)
{
if(!vis[g[x][i]])
{
int son = dfs(g[x][i]);//当前分支的儿子个数
tmp += son;//已经求出的儿子个数,相当于sum[i]
ans += (ll)(n-1-tmp)*son;
}
}
return tmp+1;
}
然后此题的正解就是C(n,3)- ans.C(n,3)表示从n个点中选3个点,C(n,3) = n*(n-1)*(n-2)/6
贴代码1:
#pragma comment(linker, "/STACK:16777216")
#include<cstdio>
#include<vector>
#define N 100010
using namespace std;
typedef long long int ll;
vector<int> g[N];
bool vis[N];
int n;
ll ans;
int dfs(int x)
{
vis[x] =;
ll sq=;//子节点个数的平方和
int tot =;//子节点个数之和
for(int i=; i<g[x].size(); ++i)
{
if(!vis[g[x][i]])
{
int son = dfs(g[x][i]);//子节点的个数
tot += son;
sq += (ll)son*son;
}
}
sq += (ll)(n-tot-)*(n-tot-);
ans += ((ll)(n-)*(n-) - sq)/;
return tot+;
}
int main()
{
freopen("1010.in","r",stdin);
while(~scanf("%d",&n))
{
for(int i=; i<=n; ++i)
{
g[i].clear();
vis[i] =;
}
for(int i=; i<n; ++i)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
ans =;
dfs();
ll sum = (ll)n*(n-)*(n-)/;
printf("%I64d\n",sum-ans);
}
return ;
}
贴代码2:
#pragma comment(linker, "/STACK:16777216")
#include<cstdio>
#include<vector>
#define N 100010
using namespace std;
typedef long long int ll;
vector<int> g[N];
bool vis[N];
int n;
ll ans;
int dfs(int x)
{
vis[x] =;
int tmp=;
for(int i=; i<g[x].size(); ++i)
{
if(!vis[g[x][i]])
{
int son = dfs(g[x][i]);//当前分支的儿子个数
tmp += son;//已经求出的儿子个数
ans += (ll)(n--tmp)*son;
}
}
return tmp+;
}
int main()
{
// freopen("1010.in","r",stdin);
while(~scanf("%d",&n))
{
for(int i=; i<=n; ++i)
{
g[i].clear();
vis[i] =;
}
for(int i=; i<n; ++i)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
ans =;
dfs();
ll sum = (ll)n*(n-)*(n-)/;
printf("%I64d\n",sum-ans);
}
return ;
}
HDU 4705 Y 树形枚举的更多相关文章
- HDU 4705 Y (2013多校10,1010题,简单树形DP)
Y Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submiss ...
- hdu 4705 Y (树形dp)
Description Input 4 1 2 1 3 1 4 题目的意思是给你一棵树,让你找到所有不在一条路径上的三个点的情况个数.乍一看正向处理比较麻烦,我们从反方向考虑,如果是取在一条路径上的3 ...
- HDU 4705 Y
Y Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submis ...
- HDOJ 4705 Y 树形DP
DP:求出3点构成链的方案数 .然后总方案数减去它 Y Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K ...
- hdu 4705(树形DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4705 思路:反面考虑,用总的方案数减去A,B,C三点在同一路径上的方案数.于是我们可以确定中间点B,在 ...
- HDU 5778 abs (枚举)
abs 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5778 Description Given a number x, ask positive ...
- HDU-4705 Y 树形DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4705 题意:给一颗树,从树上任意选择3个点{A,B,C},要求他们不在一条链上,求总共的数目. 容易想 ...
- hdu 4756 MST+树形dp ****
题意:给你n(n = 1000)个二维点,第一个点是power plant,还有n - 1个点是dormitories.然后现在知道有一条寝室到寝室的边是不能连的,但是我们不知道是哪条边,问这种情况下 ...
- hdu 4081 最小生成树+树形dp
思路:直接先求一下最小生成树,然后用树形dp来求最优值.也就是两遍dfs. #include<iostream> #include<algorithm> #include< ...
随机推荐
- linux 安装vpn
机器环境 centos Linux wdcp安装脚本和步骤第一步: wget http://www.huzs.net/soft/pptp_onekey/pptpd6.sh sh pptpd6.sh ...
- mac下安装apache+php+mysql
运行“sudo apachectl start”,再输入帐号密码,这样Apache就运行了. 运行“sudo apachectl -v”,你会看到Mac OS X 10.6.3中的Apache版本号: ...
- 在ubunut下使用pycharm和eclipse进行python远程调试
我比较喜欢Pycharm,因为这个是JetBrains公司出的python IDE工具,该公司下的java IDE工具--IDEA,无论从界面还是操作上都甩eclipse几条街,但项目组里有些人使用e ...
- 嵌套遍历<s:iterator>map=new TreeMap(string,Map(string,User))
//嵌套遍历,先给外层的map(假设是放在root中的,如果放在context的map中,要加#)取个别名,放到Actioncontext中 <s:iterator value="ma ...
- js对象的定义及处理
一,概述 在Java语言中,我们可以定义自己的类,并根据这些类创建对象来使用,在Javascript中,我们也可以定义自己的类,例如定义User类.Hashtable类等等. 目前在Javascrip ...
- Ogre 1.8 terrain 和 paging 组件
以下转自:http://hi.baidu.com/xocoder/item/e8d87cf53d87612b753c4cfd OGRE地形生成 OGRE可以通过两个接口来生成地形,分别是void Te ...
- ajax注释
//xmlHttpRequest,但是这个对象只是在火狐,google...//在中国用的最广泛的IE浏览器里面是没有这个对象的//在IE里面是用的一个控件来解决这个问题,ActiveXObject/ ...
- UIWebView的缓存策略,清除cookie
缓存策略 NSURLRequestCachePolicy NSURLRequestUseProtocolCachePolicy缓存策略定义在 web 协议实现中,用于请求特定的URL.是默认的URL缓 ...
- 如何将内存图像数据封装成QImage
http://blog.csdn.net/lyc_daniel/article/details/9055787 当采用Qt开发相机数据采集软件时,势必会遇到采集内存图像并进行处理(如缩放.旋转)操作. ...
- 如何在ubuntu 12.04 中安装经典的 GNOME桌面
这次介绍的是如何在ubuntu 12.04 中安装经典的 GNOME桌面,默认的 Ubuntu 12.04 默认unity桌面,一些用户不喜欢 Unity 桌面,所以想找回昔日的经典Gnome桌面. ...