Avito Code Challenge 2018 C. Useful Decomposition

C. Useful Decomposition

Ramesses knows a lot about problems involving trees (undirected connected graphs without cycles)!

He created a new useful tree decomposition, but he does not know how to construct it, so he asked you for help!

The decomposition is the splitting the edges of the tree in some simple paths in such a way that each two paths have at least one common vertex. Each edge of the tree should be in exactly one path.

Help Remesses, find such a decomposition of the tree or derermine that there is no such decomposition.

Input

The first line contains a single integer nn (2n1052≤n≤105) the number of nodes in the tree.

Each of the next n1n − 1 lines contains two integers aiai and bibi (1ai,bin1≤ai,bi≤naibiai≠bi) — the edges of the tree. It is guaranteed that the given edges form a tree.

Output

If there are no decompositions, print the only line containing "No".

Otherwise in the first line print "Yes", and in the second line print the number of paths in the decomposition mm.

Each of the next mm lines should contain two integers uiuivivi (1ui,vin1≤ui,vi≤nuiviui≠vi) denoting that one of the paths in the decomposition is the simple path between nodes uiui and vivi.

Each pair of paths in the decomposition should have at least one common vertex, and each edge of the tree should be presented in exactly one path. You can print the paths and the ends of each path in arbitrary order.

If there are multiple decompositions, print any.

Examples
input
Copy
4
1 2
2 3
3 4
output
Copy
Yes
1
1 4
input
Copy
6
1 2
2 3
3 4
2 5
3 6
output
Copy
No
input
Copy
5
1 2
1 3
1 4
1 5
output
Copy
Yes
4
1 2
1 3
1 4
1 5

题意:给你一棵树,把树拆成多条路径,每条路径都是独立的,比如1-2-3   1-2-4   那么1-2这条路就重复用了,这个拆法就不合法。同时所有路径至少要有一个公共点。说白了就是选一个节点为起点,从该起点出发,能够不重复的遍历所有节点,把每条路的起点终点输出即可。

思路:在纸上画一下,可以发现节点入度>=3的只能有一个,否则一定有路径会被重复使用。

记录下所有节点的入度,注意是无向图,1-2即:1和2的入度同时+1。找到>=3的节点,超过一个即判定NO。

如果该节点唯一,即以该节点为起点x,所有叶子节点为终点yi(入度==1的),输出x yi就是答案。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#define ll long long
#define exp 1e-8
#define mst(a,k) memset(a,k,sizeof(a))
#define pi acos(-1.0)
using namespace std;
ll in[100010];
ll n;
int main()
{
    ll x,y;
    while(~scanf("%lld",&n))
    {
        mst(in,0);
        for(ll i=1;i<n;i++)
        {
            scanf("%lld%lld",&x,&y);
            in[x]++;
            in[y]++;
        }
        if(n==2)   //需要特判
        {
            printf("Yes\n");
            printf("1\n");
            printf("%lld %lld\n",x,y);
            continue;
        }
        ll ok=0,root=0,cnt=0;
        for(ll i=1;i<=n;i++)   //找到>=3的节点,作为起点并记录
        {
            if(in[i]>=3)
            {
                root=i;
                ok++;
            }
            else if(in[i]==1)
            {
                cnt++;
            }
        }
        if(root==0)   //如果没有>=3,那么随便找一个非叶子的就行
        {
            for(ll i=1;i<=n;i++)
            {
                if(in[i]==2)
                {
                    root=i;
                    break;
                }
            }
        }
        if(ok>1)printf("No\n");   //节点>=3超过一个判定NO
        else
        {
            printf("Yes\n");
            printf("%lld\n",cnt);
            ll cnt=0;
            for(ll i=1;i<=n;i++)
            {
                if(in[i]==1)
                {
                    printf("%lld %lld\n",root,i);   //输出起点配对的叶子
                }
            }
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/s540239976/article/details/80969421