zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第二场)C.Cover the Tree(树性转线性,dfs序)

    地址:https://ac.nowcoder.com/acm/contest/5667/C

    题意:

    给定一个k个节点的无根树,求最少的链覆盖树上的所有边。并输出覆盖方式(链的两边的节点编号)

    解析:

    保证每一个边都有被覆盖,肯定与叶子节点有关系。

    有结论:

    用最少条链来覆盖一棵树的时候,最优解: (叶子结点数+1) / 2

    对于叶子结点的求法,可以用vector建图,求叶子结点的dfs序:

    dfs(i,-1);
    int dfs(int now,int fa)//fa防止走回头路!
    {
        if(v[now].size()==1)
        {
            a[tot++]=now;
            return 0;
        }
        for(int i=0;i<v[now].size();i++)
        {
            if(v[now][i]!=fa)
            {
                dfs(v[now][i],now);
            }
        }
    }

    网上找的专业分析:

     叶子结点:i与(i+sum/2)连接即可。

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int maxn=2e5+20;
    vector<int>v[maxn];
    int d[maxn],a[maxn];
    int tot=1;
    int sum=0;
    int dfs(int now,int fa)
    {
        if(v[now].size()==1)
        {
            a[tot++]=now;
            return 0;
        }
        for(int i=0;i<v[now].size();i++)
        {
            if(v[now][i]!=fa)
            {
                dfs(v[now][i],now);
            }
        }
    }
    int main()
    {
        int n;
        cin>>n;
        for(int i=1;i<n;i++)
        {
            int a,b;
            cin>>a>>b;
            v[a].push_back(b);
            v[b].push_back(a);
        }
        for(int i=1;i<=n;i++)
        {
            if(v[i].size()>1)
            {
                dfs(i,-1);
                break;
            }
        }
        tot--;
        cout<<(tot+1)/2<<endl;
        for(int i=1;i<=(tot+1)/2;i++)
            cout<<a[i]<<" "<<a[i+tot/2]<<endl;
    }

    不用dfs序的简单代码:

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int maxn=2e5+20;
    int d[maxn],a[maxn];
    int main()
    {
        int n;
        cin>>n;
        for(int i=1;i<n;i++)
        {
            int a,b;
            cin>>a>>b;
            d[a]++;
            d[b]++;
        }
        int sum=0;
        int tot=1;
        for(int i=1;i<=n;i++)
        {
            if(d[i]==1)
                a[tot++]=i,sum++;
        }
        cout<<(sum+1)/2<<endl;
        for(int i=1;i<=(sum+1)/2;i++)
            cout<<a[i]<<" "<<a[i+(sum)/2]<<endl;   
    }
  • 相关阅读:
    杂七杂八注意
    数字和表达式
    小总结
    层级定位
    webdriver对象定位方法
    自动化测试第一季-selenium + python(环境搭建与基础代码解释)
    补基础—.—
    1-13 代理ARP和RARP
    Nginx/LVS/HAProxy负载均衡软件的优缺点详解
    分布式集群系统下的高可用session解决方案
  • 原文地址:https://www.cnblogs.com/liyexin/p/13326261.html
Copyright © 2011-2022 走看看