任重而道远
【问题描述】
开会,是对所有人时间的浪费,是对集体的谋杀。
山区学校的一些学生之间的关系似乎好得有点过头,以至于传出了一些(在风纪委员们看来)不好的绯闻。具体地,有n个学生,n-1条绯闻,每条绯闻的主角都是俩学生。记者们的恶趣味保证任意两个学生,可以通过若干条绯闻直接或间接地联系在一起。
于是学校打算邀请一些学生参加座谈会。
校长相信,假如邀请了某位学生x来开会,那么就能够震慑到x本人,以及和x在同一条绯闻里的学生们。
矿泉水是宝贵的,校长想知道最少需要请多少人来开会,才有可能震慑到所有同学。
【输入】
第一行是 n 表示学生数。
之后n-1行,每行俩整数x,y,表示学生x和y之间有绯闻。( x≠y,但不一定x<y )
【输出】
一行,一个整数表示最少要邀请多少人。
【输入输出样例】
CP.in |
CP.out |
5 1 3 5 2 4 3 3 5
|
2 |
【数据范围】
对于前10%的数据,n<=15
对于前30%的数据,n<=2000
对于接下来30%的数据,n<=10^5,且有俩学生需要通过n-1条绯闻才能扯上关系。
对于前100%的数据,n<=10^5,1<=x,y<=n
【样例解释】
可以选择邀请学生2&3,或者是邀请学生3&5
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
using namespace std;
const int N = 1e5 + 5;
struct Edge {
int tov, nxt;
}e[N << 1];
queue <int> q;
stack <int> st;
int num, n, root = 1, sww;
int head[N << 1], fa[N], vis[N];
void add_edge (int u, int v) {
num++;
e[num].tov = v;
e[num].nxt = head[u];
head[u] = num;
}
void get_fa (int u, int f) {
fa[u] = f;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].tov;
if (v == f) continue;
get_fa (v, u);
}
}
void bfs () {
q.push (root);
st.push (root);
while (!q.empty ()) {
int u = q.front ();
q.pop ();
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].tov;
if (v == fa[u]) continue;
q.push (v);
st.push (v);
}
}
}
void solve () {
while (!st.empty ()) {
int u = st.top ();
st.pop ();
if (!vis[u]) {
int x = fa[u];
vis[x] = 1;
for (int i = head[x]; i; i = e[i].nxt) {
int v = e[i].tov;
vis[v] = 1;
}
sww++;
}
}
}
int main () {
freopen ("CP.in", "r", stdin);
freopen ("CP.out", "w", stdout);
scanf ("%d", &n);
for (int i = 1; i < n; i++) {
int u, v;
scanf ("%d%d", &u, &v);
add_edge (u, v);
add_edge (v, u);
}
get_fa (root, 0);
bfs ();
solve ();
printf ("%d\n", sww);
return 0;
}