• 2017 Hackatari Codeathon B. 2Trees(深搜)(想法)


    B. 2Trees
    time limit per test
    0.75 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    You are given two trees with the same number of leaves L, your task is to merge the two trees' leaves in a way that ensures the following:

    • The number of colors needed to color the resulting graph such that no two adjacent nodes share the same color is minimum.
    • Each leaf in the first tree is merged into exactly one leaf from the second tree.
    • Each leaf in the second tree is merged into exactly one leaf from the first tree.
    • Nodes other than leaves are not merged.

    Note that by merging two leaves a and b, the resulting node will have both edges of a and b.

    Input

    The first line of input contains one integer N (3 ≤ N ≤ 105), the number of nodes in the first tree.

    Then follows N - 1 lines, the ith line contains two integers u and v (1 ≤ u, v ≤ N), the indices of the nodes connected by the ith edge in the first tree.

    The next line contains an integer M (3 ≤ M ≤ 105), the number of nodes in the second tree.

    Then follows M - 1 lines, the ith line contains two integers u and v (1 ≤ u, v ≤ M), the indices of the nodes connected by the ith edge in the second tree.

    It is guaranteed that the two trees will have the same number of leaves L.

    Output

    On a single line print the number of colors needed to color the resulting graph.

    Followed by L lines, the ith line of them contains two integers u and v (1 ≤ u ≤ N)(1 ≤ v ≤ M), the indices of the leaves to be merged, where u is a leaf in the first tree, and v is a leaf in the second tree.

    If there’s more than one possible solution, print any of them.

    Examples
    Input
    3
    1 2
    1 3
    3
    3 1
    2 3
    Output
    2
    2 1
    3 2
    Input
    4
    1 2
    2 3
    3 4
    3
    3 1
    1 2
    Output
    3
    4 2
    1 3
    Note
    • A tree of N nodes is a connected undirected graph with N - 1 edges.
    • A node is a leaf if and only if it is connected to at most one other node.

    In the first sample, the two trees can be illustrated as follows:

    After merging node 2 from first tree with node 1 from the second tree, and node 3 from the first tree with node 2 from the second tree, the resulting graph is illustrated in the figure below:

    The minimum number of colors required to satisfy the problem constraints is 2.

    【分析】给你两棵树,他们的叶子节点个数都为L,现在要将两棵树合并,方法是只合并叶子结点,即一一对应,合并后两个叶子结点就成了一个节点,两棵树即成了

     一个有环图。然后给节点染色,相邻节点染不同颜色,问如何合并使得颜色数最少。

    首先得想到一点,对于任何一个节点,他是可以与对面任一节点合并的。那么我们考虑一个合并后的一条支路(两个叶子结点合并后形成的),由第一棵树的根节点指向

    叶子结点u,再指向第二颗树的叶子结点,到根。root1-->u-->v-->root2,假设合并前u的深度为x,v的深度为y,则合并后支路的长度为L=x+y-1;

    若L为奇数,则我们可以选择两种颜色,分别染1,2,1,...2,1。

    若L为偶数,则我们可以选择两种颜色,分别染1,2,1,...2。

    也就是说,这个图,我们从root1-->root2染色,如果只用1,2染色,那么所有支路的长度必须同为奇或同为偶。而这个奇偶又是由合并前叶子的深度决定的,所以先DFS

    算深度,然后再if-else匹配。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <bitset>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #define rep(i,m,n) for(i=m;i<=n;i++)
    #define mod 1000000007
    #define inf 0x3f3f3f3f
    #define vi vector<int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    #define pii pair<int,int>
    #define sys system("pause")
    const int maxn=1e5+10;
    const int N=2e5+10;
    using namespace std;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;}
    int n,m,k,tot=0;
    int cnt[N],dep1[N],dep2[N];
    int a[N];
    int d[4][2]={1,0,0,1,-1,0,0,-1};
    vector<int>edg1[N],edg2[N],v1,v2;
    queue<int>odd1,even1,odd2,even2;
    void dfs1(int u,int fa){
        dep1[u]=dep1[fa]+1;
        if(edg1[u].size()==1){
            if(dep1[u]&1)odd1.push(u);
            else even1.push(u);
            return;
        }
        for(int i=0;i<edg1[u].size();i++){
            int v=edg1[u][i];
            if(v!=fa)dfs1(v,u);
        }
    }
    void dfs2(int u,int fa){
        dep2[u]=dep2[fa]+1;
        if(edg2[u].size()==1){
            if(dep2[u]&1)odd2.push(u);
            else even2.push(u);
            return;
        }
        for(int i=0;i<edg2[u].size();i++){
            int v=edg2[u][i];
            if(v!=fa)dfs2(v,u);
        }
    }
    int main()
    {
        int  x,y,ans=0,sum=0;
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            scanf("%d%d",&x,&y);
            edg1[x].pb(y);
            edg1[y].pb(x);
        }
        for(int i=1;i<=n;i++){
            if(edg1[i].size()>1){
                dfs1(i,0);
                break;
            }
        }
        scanf("%d",&m);
        for(int i=1;i<m;i++){
            scanf("%d%d",&x,&y);
            edg2[x].pb(y);
            edg2[y].pb(x);
        }
        for(int i=1;i<=m;i++){
            if(edg2[i].size()>1){
                dfs2(i,0);
                break;
            }
        }
        if(odd1.size()!=odd2.size()&&odd1.size()!=even2.size()){
            puts("3");
            for(int i=1;i<=n;i++){
                if(edg1[i].size()==1)v1.push_back(i);
            }
            for(int i=1;i<=m;i++){
                if(edg2[i].size()==1)v2.push_back(i);
            }
            for(int i=0;i<v1.size();i++){
                printf("%d %d
    ",v1[i],v2[i]);
            }
        }
        else if(odd1.size()==even2.size()){
            puts("2");
            while(!odd1.empty()){
                int od1=odd1.front();odd1.pop();
                int ev2=even2.front();even2.pop();
                printf("%d %d
    ",od1,ev2);
            }
            while(!even1.empty()){
                int od2=odd2.front();odd2.pop();
                int ev1=even1.front();even1.pop();
                printf("%d %d
    ",ev1,od2);
            }
        }
        else if(odd1.size()==odd2.size()){
            puts("2");
            while(!odd1.empty()){
                int od1=odd1.front();odd1.pop();
                int od2=odd2.front();odd2.pop();
                printf("%d %d
    ",od1,od2);
            }
            while(!even1.empty()){
                int ev1=even1.front();even1.pop();
                int ev2=even2.front();even2.pop();
                printf("%d %d
    ",ev1,ev2);
            }
        }
        return 0;
  • 相关阅读:
    BZOJ 1191 HNOI2006 超级英雄hero
    BZOJ 2442 Usaco2011 Open 修建草坪
    BZOJ 1812 IOI 2005 riv
    OJ 1159 holiday
    BZOJ 1491 NOI 2007 社交网络
    NOIP2014 D1 T3
    BZOJ 2423 HAOI 2010 最长公共子序列
    LCA模板
    NOIP 2015 D1T2信息传递
    数据结构
  • 原文地址:https://www.cnblogs.com/jianrenfang/p/6665945.html
Copyright © 2020-2023  润新知