zoukankan      html  css  js  c++  java
  • 「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);
    }
    
  • 相关阅读:
    mobileSelect学习
    使用qrcode生成二维码
    点点点右边有内容
    搜索框search
    input样式和修改
    art-template模板引擎高级使用
    Nodejs中的路径问题
    异步编程(回调函数,promise)
    在nodejs中操作数据库(MongoDB和MySQL为例)
    MongoDB数据库
  • 原文地址:https://www.cnblogs.com/lcxer/p/11857707.html
Copyright © 2011-2022 走看看