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