• 2825. 【GDOI2012】可靠道路网络


    Description

    A 国需要发展他们的道路建设,他们需要一个可靠的道路网络,使得任意一条道路瘫痪,整个国家仍然连通。作为 A 国的道路工程师,给你当前 A 国的道路图,你需要计算至少需要新建设多少条道路才能使得此道路网络是可靠的,并任意给出一种可行方案。约定 A 国有 N 个城市组成,当前有 M 条双向道路,其中两个城市之间允许存在多条道路。保证最初的道路网络中,这 N 个城市是相互连通的。

    Solution

    如果要一个图没有桥,那么只需要让这个图上的所有边都至少属于一个环即可。

    那么可以先对原图中有的环进行缩点,由于图是联通的,所有缩点之后图会变成一棵树,那么题目就是让一棵树没有桥。

    很显然的想法是叶子结点两两连边,但这两个叶子节点之间的路径一定要经过根节点,所以必须钦定一个顺序来连边。

    首先叶子结点的个数决定了要加多少条边,记作 \(x\)。为了满足要求,只需要将第 \(i\) 个和第 \(i+\lfloor \frac{x}{2}\rfloor\) 个叶子结点连起来。如果 \(x\) 是奇数,那么把随后一个叶子节点连向根即可。

    当然存在一种情况使得一棵子树内的叶子结点个数超过了 \(\lfloor\frac{x}{2}\rfloor\),这是因为根没有选择正确。如果要保证正确性,要选择树的重心作为根。

    这题数据较水,可以选择任意一个节点作为根就可以 AC。

    Code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 1005
    using namespace std;
    struct node
    {
        int to,next;
    }a[N<<1];
    int n,m,tot=1,num,top,cl,ans,mx,mxnum,ans1,ans2,d[N],dfn[N],low[N],sta[N],col[N],head[N],id[N],x[N],y[N],q[N];
    bool b[N],map[N][N];
    void add(int x,int y)
    {
        ++d[x];++d[y];
        a[++tot].to=y;a[tot].next=head[x];head[x]=tot;
        a[++tot].to=x;a[tot].next=head[y];head[y]=tot;
    }
    void dfs(int now,int fa,int lst)
    {
        dfn[now]=low[now]=++num;
        sta[++top]=now;
        for (int i=head[now];i;i=a[i].next)
        {
            if ((i^1)==lst) continue;
            int v=a[i].to;
            if (!dfn[v])
            {
                dfs(v,now,i);
                if (low[v]<low[now]) low[now]=low[v];
                else if (low[v]>dfn[now])
                {
                    ++cl;
                    while (sta[top]!=v) col[sta[top--]]=cl;
                    col[v]=cl;
                    --top;
                }
            }
            else low[now]=min(low[now],dfn[v]);
        }
    }
    void dfs1(int now,int fa)
    {
        dfn[now]=++num;
        for (int i=head[now];i;i=a[i].next)
        {
            int v=a[i].to;
            if (v==fa) continue;
            dfs1(v,now);
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;++i)
        {
            scanf("%d%d",&x[i],&y[i]);
            add(x[i],y[i]);
        }
        dfs(1,0,-1);
        ++cl;
        for (int i=1;i<=n;++i)
            id[++col[i]]=i;
        tot=0;memset(head,0,sizeof(head));memset(d,0,sizeof(d));
        for (int i=1;i<=m;++i)
            if (col[x[i]]!=col[y[i]]) add(col[x[i]],col[y[i]]);
        num=0;dfs1(1,0);
        for (int i=1;i<=cl;++i)
            if (d[i]==1) q[++ans]=i;
        printf("%d\n",(ans+1)/2);
        for (int i=1;i*2<=ans;++i)
            printf("%d %d\n",id[q[i]],id[q[i+ans/2]]);
        if (ans%2==1)
            printf("%d %d\n",id[q[1]],id[q[ans]]);
        return 0;
    }
    
  • 相关阅读:
    MySQL集群在断网后再启动报"Unable to start missing node group"问题处理
    由于OCR文件损坏造成Oracle RAC不能启动的现象和处理方法
    使用dbms_scheduler包创建定时任务
    Oracle_12c_RAC_service_died问题分析处理
    MySQL使用正则表达式比较字段中的数字
    crontab不能正确执行的问题
    Oracle 12c SYSAUX表空间不足处理-清理audsys.cli_swp$a9b5f52c$1$1表
    HyperV上的Linux虚拟机启动报panic_early_exception错误
    Nagios NSclient Failed to get CPU value: 238(_total)6: Failed to get mutex :(
    两数相加II--链表
  • 原文地址:https://www.cnblogs.com/Livingston/p/15876429.html
Copyright © 2020-2023  润新知