Problem 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.
大意是在加♂帕♂里♂大♂草♂原(自我告诫)上,有很多friends,给出两两的friends关系,两个人如果有通过不超过5个人的friends关系,就能成为friends,输出每个人能和多少人成为friends。
没思路,强行写的话就对每个点都搜,多半超时
怕是dp的思想,看了学长的代码后强行理解了...
关键两个转移方程:ch[u][j] += ch[v][j-1], fa[u][i] = fa[f][i-1] + ch[f][i-1] - ch[u][i-2];
统计ch时是先搜到底,从下往上算;统计fa时一边往下搜一边算,十分机智
算fa的时候根节点特殊处理下
#include<cstdio> #include<cstring> const int maxn = 200007; struct Edge { int v, next; }E[maxn]; int head[maxn], fa[maxn][10], ch[maxn][10];//fa[i][j]保存从i点向上距离为j的点的数目,ch是向下 int n, cur; void addedge(int u, int v) { E[cur].v = v; E[cur].next = head[u]; head[u] = cur++; } void dfsch(int u, int f) { for(int i = head[u]; ~i; i = E[i].next) { int v = E[i].v; if(v == f) continue; dfsch(v, u); for(int j = 1; j <= 6; j++) { ch[u][j] += ch[v][j-1];//关键的转移 } } ch[u][0] = 1; } void dfsfa(int u, int f) { fa[u][0] = 1; if(u != f)//根节点特殊处理下 { fa[u][1] = 1;//一个点的父节点只有一个对吧 for(int i = 2; i <= 6; i++) { fa[u][i] = fa[f][i-1] + ch[f][i-1] - ch[u][i-2];// 关键的转移 } } for(int i = head[u]; ~i; i = E[i].next) { int v = E[i].v; if(v != f) dfsfa(v, u); } } void ini() { memset(head, -1, sizeof(head)); memset(fa, 0, sizeof(fa)); memset(ch, 0, sizeof(ch)); cur = 0; } int main() { //freopen("in.txt", "r", stdin); int t; int kase = 1; scanf("%d", &t); while(t--) { scanf("%d", &n); ini(); for(int i = 1; i <n; i++) { int u, v; scanf("%d%d", &u, &v); addedge(u, v); addedge(v, u); } dfsch(1, 1); dfsfa(1, 1); printf("Case #%d:\n", kase++); for(int i = 1; i <= n; i++) { int ans = 0; for(int j = 1; j <= 6; j++) { ans += ch[i][j]; ans += fa[i][j]; } printf("%d\n", ans); } } return 0; }