1. 程式人生 > >Gym 101964C、Tree(二分+搜尋)

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();

}