buptoj 945:Emiya 树形dp
2016-03-22 12:23
295 查看
945. Emiya
时间限制 5000 ms 内存限制 65536KB
题目描述
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 toN. 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;
}
相关文章推荐
- 问题求解与程序设计作业2
- 安装KB3135173后出现,Win10系统爆发式推送重置默认应用失败通知的问题
- 多个线程ThreadLocal中存的是什么
- Python中的循环,列表推导式
- WebView 返回键 onReceivedTitle 不触发 问题解决
- Nth Highest Salary
- No adapter for handler
- Android之CookieStore的持久化
- Spring AOP切面
- 关于B/S系统中文件上传的大小限制怎么做
- C++11 新特性
- java学习笔记15--多线程编程基础2
- 再回首HTML
- 深入理解图优化与g2o:g2o篇
- java学习笔记14--多线程编程基础1
- Swift函数和闭包
- C语言中scanf函数输入回车符的问题
- 可编辑ztree节点的增删改功能图标控制---已解决
- 相机标定 单目
- 2016,不再迷茫