E. Tree with Small Distances
time limit per test: 1 second
memory limit per test: 256 megabytes
input: standard input
output: standard output
You are given an undirected tree consisting of n vertices. An undirected tree is a connected undirected graph with n−1 edges.
Your task is to add the minimum number of edges in such a way that the length of the shortest path from the vertex 1 to any other vertex is at most 2. Note that you are not allowed to add loops and multiple edges.
Input
The first line contains one integer n (2≤n≤2⋅10^5) — the number of vertices in the tree.
The following n−1 lines contain edges: edge i is given as a pair of vertices ui,vi (1≤ui,vi≤n). It is guaranteed that the given edges form a tree. It is guaranteed that there are no loops and multiple edges in the given edges.
Output
Print a single integer — the minimum number of edges you have to add in order to make the shortest distance from the vertex 1 to any other vertex at most 2. Note that you are not allowed to add loops and multiple edges.
Examples
input
7 1 2 2 3 2 4 4 5 4 6 5 7
output
2
input
7 1 2 1 3 2 4 2 5 3 6 1 7
output
0
input
7 1 2 2 3 3 4 3 5 3 6 3 7
output
1
概述
给定树,求最少添加多少边,使得节点1到所有节点的距离不超过2。
思路
本题的突破口:
- 设有任意两节点a,b,连接a-b总不比连接1-b好;
- 分析如何处理终端节点c,连接1-c总不如连接1-d,其中d是c的父节点。
按照上述规律,每次连接1与任意当前终端节点的父节点,贪心迭代即可。由于每次迭代终端节点未知,我按层(距离)从最远开始搜索终端节点。
最坏时间复杂度O(nlogn)。
虽说tutorial author认为存在O(n)dp解法,但我觉得这道题不论怎样搜索终端节点都需要O(nlogn)的复杂度,不存在O(n)的更优解法。
代码
#include<bits\stdc++.h>
using namespace std;
const int MAX=2e5+5;
bool x[MAX]{0}; //sign for search
int pre[MAX]; //father node
vector<int> nxt[MAX],d[MAX]; //nxt:adjoining nodes of i;d:nodes of distance i
int dis;
int main(){
int n;
cin>>n;
//save adjoining nodes
for(int i=0;i<n-1;i++){
int a,b;
cin>>a>>b;
nxt[a].push_back(b);
nxt[b].push_back(a);
}
//search and save nodes of each distance
x[1]=1;
dis=0;
d[0].push_back(1);
while(!d[dis].empty()){
for(auto a : d[dis])
for(auto i : nxt[a]) if(!x[i]){
x[i]=1;
d[dis+1].push_back(i);
pre[i]=a;
}
dis++;
}dis--;
//search terminal nodes by distance
int cnt=0;
while(dis>2){
for(auto a : d[dis]) if(x[a]){
cnt++;
x[pre[a]]=0;
for(auto j : nxt[pre[a]]) x[j]=0;
}
dis--;
}
cout<<cnt;
return 0;
}
http://www.cnblogs.com/hizcard/ 转载请注明出处