zoukankan      html  css  js  c++  java
  • Codeforces Beta Round #25 (Div. 2 Only) D. Roads not only in Berland(DFS+并查集)

     

    题目大意

     

    给了一个无向图,n(2<=n<=1000) 个节点 n-1 条边,每天拆一条边并新建一条边,最终使得所有的顶点连通(其实形成一棵树)

    问:最少需要几天,并且输出每天拆掉的边和新建的边

     

    做法分析

     

    首先,我们可以把每条边存下来,然后利用 DFS,遍历所有的顶点一遍,遍历的过程中,经过的边就是树边(也就是所有的不拆掉的边),剩下的所有边统统要拆掉

    利用并查集,把每个连通块用一个点代表,并统计这个连通快中需要删掉的边的个数(DFS过程中没有遍历到的边的个数)

    这里,我们需要注意到这样一个性质:只有 n-1 条边,那么,图中肯定存在一个联通快,它是一棵树或者一个孤立的节点

    最少需要的天数肯定是不能遍历到的边的数量

    那么:每一天,我们删掉一条没有遍历到的边,从这个连通块中,并引一条边出去到另一个全是树边的连通分量,注意更新删掉边以后那个连通分量的相关信息

     

    参考代码

     

    D. Roads not only in Berland
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 
     5 using namespace std;
     6 
     7 const int N=1006;
     8 
     9 struct Edge
    10 {
    11     int s, t, next;
    12     bool flag;
    13     void init(int a, int b, int c)
    14     {
    15         s=a, t=b, next=c, flag=false;
    16     }
    17 } edge[N*2];
    18 int head[N], tot;
    19 
    20 void add_edge(int s, int t)
    21 {
    22     edge[tot].init(s, t, head[s]);
    23     head[s]=tot++;
    24     edge[tot].init(t, s, head[t]);
    25     head[t]=tot++;
    26 }
    27 
    28 int n, cnt[N], fa[N];
    29 bool vs[N];
    30 
    31 void DFS(int u, int pre)
    32 {
    33     vs[u]=1;
    34     for(int e=head[u]; e!=-1; e=edge[e].next)
    35     {
    36         int v=edge[e].t;
    37         if(v==pre || vs[v]) continue;
    38         edge[e].flag=1, edge[e^1].flag=1;
    39         DFS(v, u);
    40     }
    41 }
    42 
    43 int find_fa(int x)
    44 {
    45     if(fa[x]!=x) fa[x]=find_fa(fa[x]);
    46     return fa[x];
    47 }
    48 
    49 int main()
    50 {
    51     scanf("%d", &n);
    52     memset(head, -1, sizeof head);
    53     tot=0;
    54     for(int i=1; i<=n; i++) fa[i]=i;
    55     for(int i=1, a, b; i<n; i++)
    56     {
    57         scanf("%d%d", &a, &b);
    58         add_edge(a, b);
    59         int f1=find_fa(a);
    60         int f2=find_fa(b);
    61         if(f1!=f2) fa[f1]=f2;
    62     }
    63     memset(vs, 0, sizeof vs);
    64     for(int i=1; i<=n; i++) if(!vs[i]) DFS(i, -1);
    65 
    66     memset(cnt, 0, sizeof cnt);
    67     int ans=0;
    68     for(int i=0; i<tot; i+=2) if(!edge[i].flag)
    69     {
    70         ans++;
    71         cnt[find_fa(edge[i].s)]++, cnt[find_fa(edge[i].t)]++;
    72     }
    73 
    74     printf("%d\n", ans);
    75     for(int e=0; e<tot; e+=2)
    76     {
    77         if(edge[e].flag) continue;
    78         printf("%d %d ", edge[e].s, edge[e].t);
    79         for(int i=1; i<=n; i++)
    80         {
    81             if(cnt[find_fa(i)]!=0 || find_fa(i)==find_fa(edge[e].s)) continue;
    82             printf("%d %d\n", edge[e].s, i);
    83             fa[find_fa(i)]=find_fa(edge[e].s);
    84             break;
    85         }
    86         cnt[find_fa(edge[e].s)]--, cnt[find_fa(edge[e].t)]--;
    87     }
    88     return 0;
    89 }

    题目链接 & AC通道

    Codeforces Beta Round #25 (Div. 2 Only) D. Roads not only in Berland

  • 相关阅读:
    BZOJ3473: 字符串
    BZOJ1088: [SCOI2005]扫雷Mine
    跪啃SAM
    BZOJ3932: [CQOI2015]任务查询系统
    BZOJ3545: [ONTAK2010]Peaks
    06.约束
    05.数据表的创建与简单操作
    04.数据库的创建
    安卓6.0后运行时权限封装
    OkGo使用缓存
  • 原文地址:https://www.cnblogs.com/zhj5chengfeng/p/3034313.html
Copyright © 2011-2022 走看看