Given an unrooted tree, you should choose the minimum number of chains that all edges in the tree are covered by at least one chain. Print the minimum number and one solution. If there are multiple solutions, print any of them.
输入描述:
The first line contains one integer n (1≤n≤2×105), denoting the size of the tree.
Following n−1 lines each contains two integeru,v (1≤u<v≤n), denoting an edge in the tree.
It's guaranteed that the given graph forms a tree.
输出描述:
The first line contains one integer k, denoting the minimum number of chains to cover all edges.
Following k lines each contains two integers u,v (1≤u,v≤n), denoting a chain you have chosen. Here u=v is permitted, which covers no edge.
示例1
输入
复制 5 1 2 1 3 2 4 2 5
5
1 2
1 3
2 4
2 5
输出
复制 2 2 3 4 5
2
2 3
4 5
说明
题意:就是给你一颗树,但是没有告诉你节点是什么,现在要你找出最少的链的个数要使这些链能够走过所有的边
思路:
一眼dfs序有没有,我直接记录一个点的区间l,r,如果l == r就是叶子节点,但是这个题居然wa了后来发现可以有自环,过分,所以直接根据入度判断叶子节点,然后R<=s/2,因为R是dfs序最后的叶子节点了,因此大于他的叶子节点,肯定不是在这条边为根节点的子树上,要通过这条边延伸出去,所以这条边必会被覆盖。 L>s/2,因为L是dfs序最开始的叶子节点,因此小于他的叶子节点,肯定也不是在这条边为根节点的子树上,要通过这条边延伸出去,所以这条边必会被覆盖。 R>s/2 L<=s/2,首先因为根节点至少有两个(这就是为什么要特判n=1,n=2),所以每条边的叶子范围要不 L>1,要不R<n。如果L≠1,那么这条边也必须得延伸出去才能到 ,所以肯定经过。如果R≠n,那么这条边也必须延伸出去才能到 。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
int n;
vector<int> edge[N];
int tot;
int l[N],r[N];
vector<int>ans;
void dfs(int u,int f){
if(edge[u].size() == 1)
ans.push_back(u);
for(auto v:edge[u]){
if(v == f)
continue;
dfs(v,u);
}
}
signed main()
{
cin >> n;
for(int i = 1;i < n;i ++)
{
int x,y;
cin >> x >> y;
edge[x].push_back(y);
edge[y].push_back(x);
}
dfs(1,0);
int res = 0,pos = ans.size()-1;
cout << (ans.size() + 1)/2 << '\n';
for (int i = 0; i < (ans.size() + 1)/2 ; i++)
{
cout << ans[i] << ' ' << ans[(i + ans.size()/2)%(int) ans.size()] << '\n';
}
}