HZAU 1201 Friends(树形DP 待整理)
来源:互联网 发布:淘宝手机怎么网页版 编辑:程序博客网 时间:2024/06/05 02:07
1201: Friends
Time Limit: 1 Sec Memory Limit: 1280 MBSubmit: 98 Solved: 16
[Submit][Status][Web Board]
Description
In a country, the relationship between people can be indicated by a tree. If two people are acquainted with each other, there will be an edge between them. If a person can get in touch with another through no more than five people, we should consider these two people can become friends. Now, give you a tree of N people’s relationship. ( 1 <= N <= 1e5), you should compute the number of who can become friends of each people?
Input
In the first line, there is an integer T, indicates the number of the cases.
For each case, there is an integer N indicates the number of people in the first line.
In the next N-1 lines, there are two integers u and v, indicate the people u and the people
v are acquainted with each other directly. People labels from 1.
Output
For each case, the first line is “Case #k :”, k indicates the case number.
In the next N lines, there is an integer in each line, indicates the number of people who can become the ith person’s friends. i is from 1 to n.
Sample Input
1 8 1 2 2 3 3 4 4 5 5 6 6 7 7 8
Sample Output
Case #1:67777776
HINT
Source
【题目大意】
给出一棵树,问每个节点距离六个点以内的点有几个
【题解】
定根维护树形DP,Dw[x][i]数组表示从上往下到达的距离为i的点的个数,
有Dw[x][i]=sum(Dw[son][i-1]),Up[x][i]表示从下往上距离为i的点的个数,
有Up[x][i]=Up[fx][i-1]+Dw[fx][i-1]-Dw[x][i>=2?i-2:0],
两边dfs计算出这两个值,就可以得到每个点的答案了。
官解:(here)
•F[rt][len] :节点rt的子孙里,距离rt的为len的节点个数
•ans[rt][len] : 整棵树上,距离rt为len的节点个数
•F值一次简单的深搜可以得到
•而ans[rt][len] = F[rt][len] + ans[fa(rt)][len – 1] – F[fa(rt)][len – 1]
参考:here
#include <cstdio>#include <algorithm>#include <vector>#include <cstring>using namespace std;const int N=100010;vector<int> v[N];int Dw[N][10],Up[N][10];void dfs(int x,int fx){ Dw[x][0]=1; for(int i=0;i<v[x].size();i++)if(v[x][i]!=fx){ dfs(v[x][i],x); for(int j=1;j<=6;j++)Dw[x][j]+=Dw[v[x][i]][j-1]; }}void dfs2(int x,int fx){ Up[x][0]=1; if(x!=fx){for(int i=1;i<=6;i++)Up[x][i]=Up[fx][i-1]+Dw[fx][i-1]-Dw[x][i>=2?i-2:0];} for(int i=0;i<v[x].size();i++)if(v[x][i]!=fx){dfs2(v[x][i],x);}}int T,n;int main(){ scanf("%d",&T); for(int cas=1;cas<=T;cas++){ printf("Case #%d:\n",cas); scanf("%d",&n); for(int i=1;i<=n;i++)v[i].clear(); memset(Dw,0,sizeof(Dw)); memset(Up,0,sizeof(Up)); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); v[x].push_back(y); v[y].push_back(x); }dfs(1,1); dfs2(1,1); for(int i=1;i<=n;i++){ int res=0; for(int j=1;j<=6;j++)res=res+Up[i][j]+Dw[i][j]; printf("%d\n",res); } }return 0;}
here
/**Problem C Friends题意:给n个人,有n-1个朋友关系,形成一棵树,如果两个人能够通过不超过5个人可以联系到,那么那两个人也是朋友,问你每个人有多少个朋友,比如(1-2-3-4-5-6-7-8),1可以联系到2 3 4 5 6 7,所以1有6个朋友思路:先对树进行dfs搜索形成有向树,根节点为1(任意),在设son[o][i]表示以o为节点在通过恰好i个人联系可以成为朋友的个数,只计算在根为o的子树中的结果,那么设p1,p2,p3,p4,p5,p6为o的一级祖先、二级祖先、..六级祖先那么对于节点o来说, 不通过p1能成为朋友的个数为 sigma {son[o][i] | 0 <= i <= 6}, 计算的是包含o节点的不通过p2而通过p1能成为朋友的个数为 sigma {son[p1][i] | 0 <= i <= 5}但是这里再次计算了经过o的情况, 所以需要减去 sigma {son[p1][i] | 0 <= i <= 4}同理需要经过Pj祖先的时候, 总个数为 sigma {son[Pj][i] | 0 <= i <= 6 - j}但是不能再通过Pj-1, 所以减去 sigma {son[Pj-1][i] | 0 <= i <= 6 - j - 1}所有pj的结果加起来再减去1就是答案了, 因为把o节点自己计算了在内**/#include<cstdio>#include<cstring>#include<vector>#include<algorithm>const int maxn = 1e5 + 10;using namespace std;int T, n, kase = 1;int pre[maxn];vector<int> G[maxn];int son[maxn][7];int que[10];void dfs(int fa[7], int u) { int fat = fa[5]; pre[u] = fat; for(int i = 0; i <= 5; i++) { int f = fa[i]; son[f][6 - i]++; } int nf[7] = {fa[1], fa[2], fa[3], fa[4], fa[5], u}; for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(v == fat) continue; dfs(nf, v); }}int main() { scanf("%d", &T); while(T--) { scanf("%d", &n); memset(son, 0, sizeof son); for(int i = 0; i <= n; i++) { son[i][0] = 1; G[i].clear(); for(int j = 1; j < 7; j++) son[i][j] = 0; } for(int i = 1; i < n; i++) { int u, v; scanf("%d %d", &u, &v); G[u].push_back(v); G[v].push_back(u); } int f[7] = {0, 0, 0, 0, 0, 0}; dfs(f, 1); printf("Case #%d:\n", kase++); for(int i = 1; i <= n; i++) { int ans = 0; for(int j = 0; j <= 6; j++) ans += son[i][j]; int u = i; for(int j = 1; j <= 6; j++) { int v = u; u = pre[u]; if(u == 0) break; for(int k = 0; k <= 6 - j; k++) ans += son[u][k]; for(int k = 0; k <= 6 - j - 1; k++) ans -= son[v][k]; } printf("%d\n", ans - 1); } } return 0;}
- HZAU 1201 Friends(树形DP 待整理)
- HZAU 1201 Friends(树形dp)
- hdu5119 Happy Matt Friends--dp(待解决)
- 概率DP总结(待整理)
- DP待整理
- hzau1201——Friends(树形DP)
- HZAU校赛F题 LCS (dp)
- HZAU--21--Arithmetic Sequence(二维dp)
- 树形DP整理小结
- 树形DP例题整理
- POJ3666 Making the Grade(DP,离散化 待整理)
- HZAU 1199 Little Red Riding Hood (dp)
- HZAU 1199 Little Red Riding Hood(水DP)
- hdu4126 Genghis Khan the Conqueror--最小生成树 & 树形DP(待解决)
- HZAU 1019 Arithmetic Sequence [DP]
- 树链剖分(待整理)
- lightoj 1201 树形dp
- hdu5119 Happy Matt Friends(dp)
- JAVA的静态变量、静态方法、静态类
- Android Studio导入项目时出现,弹框说SDK有问题
- 对象锁和类锁是否会互相影响?
- linux上jni调用注意事项
- socket通信
- HZAU 1201 Friends(树形DP 待整理)
- BZOJ 2120 数颜色——带修改的莫队算法
- hdu1728逃离迷宫(BFS)
- C#中接口的显式和隐式实现
- BNUOJ Training Plan
- MySQL事务 索引
- STM32:I2C接口读写EEPROM(AT24C02)试验例程
- Contest 798 C&&D
- 第四十讲项目六 三色球问题