题目 B : 树上分支

题目描述 

有的时候,题目和内容是没有一点关系的。

当然,作为一个有责任心的出题者,会把题目和名字紧紧联系在一起。

显然,小花不是一个有责任心的出题者。

由于他想尽早的完成出题任务,于是他把出题的流程抽象成了一棵树。

例如,当出完题目后,小花可以选择先写标程,或是先造数据。但找人验题,一定是在造完数据以后。 他现在正处在其中的某个阶段,你可以把所有的阶段都视为一个点。

烦人的 boss 又在催促他,并询问最快还有多久才能到第 x 个阶段。 所有的询问相互独立。

输入 

第一行一个整数 T,代表 T 组数据。(T<=500)

接下来每行三个数 n,m,r。代表有 n 个阶段,m 个询问,小花现在正处在 第 r 个阶段。(1<=n,m<=100000)

接下来 n-1 行,每行两个数,u,v,代表 v 阶段在 u 阶段之后。(1<=u,v<=n)

接下来一行有 m 个数,代表 boss 询问到第 x 个阶段还有多久。(1<=x<=n)

输出 

对于每组数据,输出 m 个数,代表小花最快还有几步才能到要求的阶段。

如果小花已经完成了 boss 询问的那个阶段,那么对此询问输出 0。

如果无法确定小花是不是完成了那个阶段,输出-1。

如果询问的就是小花所在的阶段,输出 0。

每个询问后输出一个空格,每组数据后输出一个换行。

样例输入

1
5 2 1
1 2
1 3
2 4
2 5
3 4

样例输出

1 2

解题思路

下班补上,注意用cin、cout会超时,这里使用scanf()、printf()

参考代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
  
using namespace std;
int step[100010];
vector<int> tree[100010];
vector<int> father[100010];

bool vis[100010];

void dfs(int u)
{
	int l=tree[u].size();
	for(int i=0; i<l; i++)
	{
		if(step[tree[u][i]] == -1)
		{
			step[tree[u][i]] = step[u]+1;
		}
		else 
		{
			step[tree[u][i]] = min(step[u]+1, step[tree[u][i]]);
		}

		dfs(tree[u][i]);
	}
}

void dfs1(int u)
{
	int l=father[u].size();
	for(int i=0; i<l; i++)
	{
		if(vis[father[u][i]] == false)
		{
			vis[father[u][i]] = true;
			step[father[u][i]] = 0;
			dfs1(father[u][i]);
		}
	}
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
	{
		memset(vis, false, sizeof(vis));
		memset(tree, 0, sizeof(tree));
		memset(father, 0, sizeof(father));
		memset(step, -1, sizeof(step));

		int n,m,r;

		scanf("%d%d%d",&n, &m, &r);

		for(int i=1;i<n;i++)
		{
			int u,v;
			scanf("%d%d",&u, &v);
			tree[u].push_back(v);
			father[v].push_back(u);
		}

		vis[r]=true;
		step[r]=0;
		dfs1(r);
		dfs(r);

		int res;

		for(int i=1; i<=m; i++)
		{
			scanf("%d", &res);
			printf("%d ", step[res]);
		}
		printf("\n");
	}
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

js君

关注我,还有跟多干货

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值