• 「BalticOI 2015」网络


    题意简述:给你一颗(n)个点的树,问你至少需要加几条边,可以使得这棵树删去任意一条边后依然联通。并给出一种方案。

    很显然可以转化为对于树的任意一颗子树,都需要连一条边到其他子树,显然连叶子节点是最优的。

    考虑这样一种连边方案:设一共(k)个叶子节点,按(dfs)序排序,第(i)个叶子节点连向第(i+lceilfrac{k}{2} ceil)个叶子节点,容易证明这样连边一定不会存在一颗子树内没有边连向其他子树。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<set>
    using namespace std;
    #define rg register
    void read(int &x){
        char ch;bool ok;
        for(ok=0,ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')ok=1;
        for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());if(ok)x=-x;
    }
    const int maxn=5e5+10;
    int n,m,in[maxn],rt,dfn[maxn],id,k,w[maxn],nid[maxn];
    int pre[maxn*2],nxt[maxn*2],h[maxn],cnt;
    void ins(int x,int y){
        pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt;
        pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt;
    }
    void dfs(int x,int fa){
        dfn[x]=++id;nid[id]=x;
        for(rg int i=h[x];i;i=nxt[i])
    	if(pre[i]!=fa)dfs(pre[i],x);
        if(in[x]==1)w[++k]=dfn[x];
    }
    int main(){
        read(n);
        for(rg int i=1,x,y;i<n;i++)read(x),read(y),ins(x,y),in[x]++,in[y]++;
        for(rg int i=1;i<=n;i++)if(in[i]!=1){rt=i;break;}
        dfs(rt,0);printf("%d
    ",(k+1)/2);
        for(rg int i=1;i<=k/2;i++)printf("%d %d
    ",nid[w[i]],nid[w[i+(k+1)/2]]);
        if(k&1)printf("%d %d
    ",nid[w[k/2+1]],rt);
    }
    
  • 相关阅读:
    HTML简介(一)
    Bootstrap简介--目前最受欢迎的前端框架(一)
    命名空间--名称解析规则
    SpringMVC概述(2)
    MVC模型概述(1)
    Luogu P2831 【NOIP2016】愤怒的小鸟|DP
    【学习笔记】凸包
    【学习笔记】Floyd的妙用
    Luogu P2886 [USACO07NOV]牛继电器Cow Relays|最短路,倍增
    Luogu P5463 小鱼比可爱(加强版)|树状数组
  • 原文地址:https://www.cnblogs.com/lcxer/p/11857707.html
Copyright © 2020-2023  润新知