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< ...
随机推荐
- 让webapi只接受ajax请求
为了测试先做一个简单的webapi,直接用新建项目时默认的就可以了. 在浏览器中测试request get,得到结果 然后再项目中新建一个AjaxOnly的类 AjaxOnly继承Acti ...
- MySql插入记录时判断
我们在开发数据库相关的逻辑过程中, 经常检查表中是否已经存在这样的一条记录, 如果存在则更新或者不做操作, 如果没有存在记录,则需要插入一条新的记录. 这样的逻辑固然可以通过两条sql语句完成. SE ...
- 中南民航如何利用K2BPM构建业务流程?
广州市中南民航空管通信网络科技有限公司成立于2004年9月,负责民航中南地区通信网络.电报网络的建设与维护.民航空管信息系统的开发与维护.公司拥有一支技术精湛的研发队伍,在信息技术领域领跑于民航空管行 ...
- hdu 1030 Delta-wave (C++, 0ms, explanatory comments.) 分类: hdoj 2015-06-15 12:21 45人阅读 评论(0) 收藏
problem description http://acm.hdu.edu.cn/showproblem.php?pid=1030 #include <cstdio> #include ...
- xlistview的java(头)
package com.bwie.xlistviews; import com.bwie.test.R; import android.content.Context;import android.u ...
- MapReduce 重要组件——Recordreader组件
(1)以怎样的方式从分片中读取一条记录,每读取一条记录都会调用RecordReader类: (2)系统默认的RecordReader是LineRecordReader,如TextInputFormat ...
- hdu 2082
ps:get到了母函数...看了好久的模板与介绍....似懂非懂..决定要多找些题来试试... 代码: #include "stdio.h" #include "stri ...
- CentOS中vsftp安装与配置
http://blog.chinaunix.net/uid-7271021-id-3086186.html 553 Could not create file 解决办法 [root@localhost ...
- Python 安全类目推荐 (持续更新)
推荐学习书目 › Learn Python the Hard Way › Python 学习手册 › Python Cookbook › Python 基础教程 Python Sites › PyPI ...
- Android Launcher 详解
(1) Launcher的定义:Android系统启动后,加载的第一个程序,是其他应用程序的入口. (2) Launcher的构成:HomeScreen(1.workspace(A ...