• POJ P3352 Road Construction 解题报告


    P3352 Road Construction

    描述

    这几乎是夏季,这意味着它几乎是夏季施工时间!今年,负责岛屿热带岛屿天堂道路的优秀人士,希望修复和升级岛上各个旅游景点之间的各种道路。

    道路本身也很有趣。由于岛上奇特的风俗习惯,道路的布置使得它们不会在十字路口相遇,而是通过桥梁和隧道在彼此之间穿过或穿过。这样,每条道路都在两个特定的旅游景点之间运行,这样游客不会失去不可挽回的收入。

    不幸的是,鉴于每条道路上所需的维修和升级的性质,当建筑公司在特定的道路上工作时,它在任何方向都不可用。如果不能在两个旅游景点之间旅行,即使建筑公司在任何特定时间只在一条道路上工作,这也可能导致问题。

    因此,偏远岛道路部已决定请求您的咨询服务来帮助解决这个问题。已经决定在各个景点之间建造新的道路,使得在最终配置中,如果任何一条道路正在建设中,则仍有可能使用剩余道路在任何两个旅游景点之间旅行。你的任务是找到必要的最少数量的新道路。

    输入

    第一行输入由正整数(n)(r)组成,用空格隔开,其中(3≤n≤1000)是岛上旅游景点的数量,(2≤r≤1000)是道路数量。旅游景点可方便地标记为1至(n)。下列(r)行中的每一行都由两个整数组成,(v)(w)之间用空格隔开,表示标记为(v)(w)的景点之间存在道路。请注意,您可以沿着每条道路向两个方向行驶,任何一对旅游景点最多只能有一条道路在它们之间。此外,您可以放心,在目前的配置中,可以在任何两个旅游景点之间旅行。

    输出

    一行,由一个整数组成,它给出我们需要添加的最少道路数量。


    谷歌翻译的。海星。

    题目简化:对于一个联通图,加最少的边使图成为一个边双联通图。

    可以看出,对于环上的任何一条边,割去都是没有影响的,我们可以先缩点,将图缩成一个树。然后对树做讨论。

    对树中度为1的点,我们一定要把这个点再连一个边,此时用贪心的思想,同样使它连接其他度为1的点。对于度不为1的点,我们割去任何一条与它相连的边后它都可以通过度为1的点新连得边跑走。所以答案为(lceil d/2 ceil)

    在做法上,也可以不缩点做,甚至是思想上。

    在题目HNOI2012 矿场搭建中,我们用了这样的思想。

    讨论每一个联通块中由割点相连接的若干个强连通分量(等效为去掉割点),讨论这个强连通分量与多少个割点相连做出决策。

    对于这个题,我们可以考虑与割边相连的环。
    若一个环与一个割边相连,则割去这个边后不能与其他的联通,得连走一条,等效为缩点后度为1的点。
    若一个环与多个割边相连,无所谓啊。

    【拓展】由此我们也可以由割边在无向图找环了。

    这样写起来也比较简单了。


    code:

    #include <cstdio>
    int min(int x,int y){return x<y?x:y;}
    const int N=1010;
    struct Edge
    {
        int to,next;
    }edge[N<<1];
    int head[N],cnt=1,cntt=0,n,m;
    void add(int u,int v)
    {
        edge[++cnt].next=head[u];edge[cnt].to=v;head[u]=cnt;
    }
    int time=0,low[N],dfn[N],ans=0,c[N],is[N],used[N];
    void tarjan(int now,int fa)
    {
        low[now]=dfn[now]=++time;
        for(int i=head[now];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(!dfn[v])
            {
                tarjan(v,now);
                low[now]=min(low[v],low[now]);
                if(low[v]>dfn[now])
                    is[i]=1,is[i^1]=1;
            }
            else if(fa!=v)
                low[now]=min(low[now],dfn[v]);
        }
    }
    void dfs(int now)
    {
        used[now]=1;
        for(int i=head[now];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(is[i])
                cntt++;
            else if(!used[v])
                dfs(v);
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int u,v;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v),add(v,u);
        }
        for(int i=1;i<=n;i++)
            tarjan(i,0);
        for(int i=1;i<=n;i++)
            if(!used[i])
            {
                cntt=0;
                dfs(i);
                if(cntt==1) ans++;
            }
        printf("%d
    ",ans+1>>1);
        return 0;
    }
    
    

    2018.6.9

  • 相关阅读:
    IDEA创建MAVEN JavaWeb项目中 Target文件夹中没有lib包
    2019年上半年下午第六题
    2021年上半年下午第六题
    2019年下半年下午第六题
    软考2019下半年下午第三题
    软考2019年下半年下午第二题
    2019年下半年软考下午第一题
    软考2019年上半年下午第三题
    2019软考上半年下午第二题
    2019年上半年软考下午题第一题
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9160194.html
Copyright © 2020-2023  润新知