您的位置:首页 > 其它

buptoj 945:Emiya 树形dp

2016-03-22 12:23 295 查看


945. Emiya

时间限制 5000 ms 内存限制 65536
KB


题目描述

There are N Assassin in a town. Each of them hides in a building and there aren't no two paths between any two of Assasin (You could think the buildings form a tree),every building has a number which is from 1 to
N. Now Emiya comes to the town. As an Archer ,Emiya could shoot any enimy even though it is far away from him . And Archer wants to know ,how many Assassins are exactly d kilometers away from him if he comes to a building numbered x? You could think every
buildings is 1 kilometers away from its neighbors.


输入格式

There are multiple test cases. Please process till EOF. The number of test cases is not exceed 100.
The first line contains two number N and Q,which indicate the number of Assassins(Buildings) and the number of questions Emiya would ask.
Then following N-1 lines ,each line contains two number u and v,indicating there is a road between buildings u and buildings v.
The next Q lines are questions, each line contains two number x and d ,indicating the Building where Emiya comes in and the distance.
(1≤N,Q≤105,d≤10)


输出格式

For each questions : ouput how many Assasins are exactly d kilometers away from the Building x.


输入样例

6 5
3 2
3 4
4 5
4 6
4 1
5 2
1 0
3 2
3 1
5 3



输出样例

3
1
3
2
1


题意:给定一棵树,有Q个询问,每次询问是到某一个节点距离为d的节点有多少个。d<=10。

两次深搜,一次搜寻下面到自己距离为d的个数,即以自己为根节点,子节点距离自己距离为d的个数。

第二次搜是要加上上面距离自己距离为d的个数,all[x][d]=down[x][d]+all[fa][d-1]-down[x][d-2]。即上面节点到父节点距离为d-1的到该节点距离就是d了,但是这里面包括了自己的子节点,所以要剪掉到自己距离为d-2的节点。

代码:

/*
USER_ID: test#299792458ms
PROBLEM: 945
SUBMISSION_TIME: 2016-03-21 18:19:18
*/

#pragma warning(disable:4996)
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <ctime>
#include <set>
#include <map>
using namespace std;
typedef long long ll;

#define INF 0x33ffffff

#define eps 1e-6
const ll mod = 1000000007;
const int maxn = 1e5 + 5;
const double PI = acos(-1.0);

int n, q, edgen;
int head[maxn], vis[maxn];
int all[maxn][12],down[maxn][12];

struct ed
{
int to;
int next;
}edge[maxn * 3];

void addedge(int st, int to)
{
edgen++;
edge[edgen].to = to;
edge[edgen].next = head[st];
head[st] = edgen;
}
void init()
{
edgen = 0;
memset(all, 0, sizeof(all));
memset(down, 0, sizeof(down));
memset(head, -1, sizeof(head));
for (int i = 0; i <= n; i++)
{
down[i][0] = 1;
}
}

void dfs1(int x)
{
int i, j, k;
for (i = head[x]; i != -1; i = edge[i].next)
{
k = edge[i].to;
if (vis[k] == 0)
{
vis[k] = 1;
dfs1(k);
for (j = 1; j <= 10; j++)
{
down[x][j] += down[k][j - 1];
}
}
}
}

void dfs2(int x, int fa)
{
int i, j, k;
for (i = 0; i <= 10; i++)
{
all[x][i] = down[x][i];
}
if (fa != -1)
{
for (i = 1; i <= 10; i++)
{
all[x][i] += all[fa][i - 1];
if (i > 1)all[x][i] -= down[x][i - 2];
}
}
for (i = head[x]; i != -1; i = edge[i].next)
{
k = edge[i].to;
if (vis[k] == 0)
{
vis[k] = 1;
dfs2(k, x);
}
}
}

void solve()
{
int i, j, k;
int u, v;
for (i = 1; i <= n - 1; i++)
{
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
memset(vis, 0, sizeof(vis));
vis[1] = 1;
dfs1(1);

memset(vis, 0, sizeof(vis));
vis[1] = 1;
dfs2(1, -1);

for (i = 1; i <= q; i++)
{
scanf("%d%d", &u, &v);
printf("%d\n", all[u][v]);
}
}

int main()
{
#ifdef wangchong756
freopen("i.txt", "r", stdin);
freopen("o.txt", "w", stdout);
int time_wangchong756 = clock();
#endif
while (scanf("%d%d", &n, &q) != EOF)
{
init();
solve();
}
//system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: