Gym 101964C、Tree(二分+搜索)

                                                 Problem C Tree

Input File: standard input

Output File: standard output

Time Limit: 0.1 seconds (C/C++)

Memory Limit: 256 megabytes

You are given a tree of n vertices, each with a unique number from 1 to n. A vertex has a color, black or white. Choose exactly m black vertices so that the length of the longest path between any of them is minimal. Input The first line contains two integers n and m (1 ≤ m ≤ n ≤ 100) — the number of vertices and the number of black vertices you have to choose. The fourth line contains n integers p1, p2, . . . , pn (0 ≤ pi ≤ 1). If the pi = 1, then the i-th vertex is black; otherwise, it is white. It is guaranteed that the number of black vertices is at least m. Each of the next n − 1 lines contains two integers vi and ui (1 ≤ vi , ui ≤ n) meaning that there is an edge between vi and ui . It is guaranteed that the input graph is a tree. Output Print a single integer — the answer to the task.

Sample input

6 3
1 1 0 1 1 1
1 2
1 3
1 4
3 5
3 6
9 4 
1 0 1 0 1 0 0 1 1
1 2
2 4
2 3
4 5
1 6
6 7
6 8
7 9

Sample output 

2

5

Note In the first example, the only option is to choose 1, 2, and 4. The maximum distance will be 2. In the second example, you can choose 1, 3, 8, and 9. The maximum distance will be between 3 and 9.

 

一、原题地址

点我传送

 

二、大致题意

给出一个n个顶点的树,每个顶点可以是黑色也可以是白色。给出一个数m,询问在图上选择m个黑点他们之间的最大距离的最小值是多少。

 

三、大致思路

二分最大的距离,对于每个二分到的mid值用BFS+DFS来寻找是否满足条件。vis[ i ]数组用以记录一个点在BFS中是否被遍历到,当一个数被遍历到的时候,显然他是处在这颗树的末端的,也就是说我们寻找最大的距离就是DFS能跑的最远距离。

 

四、代码

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;


int n, m;
int color[105];
bool vis[105];
int maxx;
vector<int>e[105];
int st;
struct Node
{
	int id;
	int step;
};
void prework()
{
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &color[i]);
	}
	for (int i = 1; i <= n - 1; i++)
	{
		int u, v;
		scanf("%d %d", &u, &v);
		e[u].push_back(v);
		e[v].push_back(u);
	}
}

int DFS(int nx, int pre, int maxx, int dep)
{
	int res = color[nx];
	int S = e[nx].size();
	for (int i = 0; i < S; i++)
	{
		int to = e[nx][i];
		if (vis[to]&&dep+1<=maxx&&to!=pre)
		{
			res += DFS(to, nx, maxx, dep + 1);
		}
	}
	return res;
}

bool check(int nowl)
{
	memset(vis, false, sizeof(vis));
	queue<int>q;
	q.push(1);
	while (!q.empty())
	{
		int t = q.front();
		q.pop();
		vis[t] = true;		//标记打的位置要正确
		int num = DFS(t, -1, nowl, 0);
		if (num >= m)return true;
		int S = e[t].size();
		for (int i = 0; i < S; i++)
		{
			int to = e[t][i];
			if (!vis[to])
			{
				q.push(to);
			}
		}
	}
	return false;
}
int Mainwork()
{
	int l = 0, r = n;
	int mid, ret;
	while (l <= r)
	{
		mid = (l + r) >> 1;
		if (check(mid))
		{
			r = mid - 1;
			ret = mid;
		}
		else
			l = mid + 1;
	}
	return ret;
}
int main()
{
	prework();
	printf("%d\n", Mainwork());
	getchar();
	getchar();

}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值