zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第三场)G Operating on a Graph 题解

    题意

    给一张n个点m条边的无向图,一开始 i 号点属于第 i 个集合,每次对一个集合进行操作,将与该集合中的点相连的点所处的集合归到该集合中,有无效操作,Q次操作过后询问每个点所处集合。

    看到这道题首先想到的就是并查集,但是无法快速能够向集合外连边的点。

    我们可以发现这样一个性质,一个点作为集合边上的一点向外延伸最多进行一次,所以我们每次A集合向B集合合并的时候由B集合向A集合连边,下次对B集合操作的时候就遍历与它连通的集合,然后看这些集合所代表的点是否能向外连边,因为每个点只会向外扩展一次,所以便利之后就可以将邻接表重置。最后复杂度O( n log n )

     1 #include<iostream>
     2 #include<cstdlib>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<cstring>
     6 #define N 1000005
     7 using namespace std;
     8 int T,n,m;
     9 int zz1,zz2,zz3,a1[N],a2[N],a3[N];
    10 struct ro{
    11     int to,next;
    12 }road1[N*2],road2[N*2];
    13 void build1(int x,int y)
    14 {
    15     zz1++;
    16     road1[zz1].to=y;
    17     road1[zz1].next=a1[x];
    18     a1[x]=zz1;
    19 }
    20 void build2(int x,int y)
    21 {
    22     zz2++;
    23     road2[zz2].to=y;
    24     road2[zz2].next=a2[x];
    25     a2[x]=zz2;
    26 }
    27 bool fw[N];
    28 int fa[N],Q,tmp[N],cnt;
    29 int find(int x)
    30 {
    31     if(fa[x]==x)return x;
    32     return fa[x]=find(fa[x]);
    33 }
    34 void dfs(int x)
    35 {
    36     for(int i=a2[x];i;i=road2[i].next)
    37     {
    38         int y=road2[i].to;
    39         dfs(y);
    40     }
    41     for(int i=a1[x];i;i=road1[i].next)
    42     {
    43         int y=road1[i].to;
    44         if(find(y)!=find(x)&&!fw[find(y)])
    45         {
    46             fw[find(y)]=1;
    47             cnt++;
    48             tmp[cnt]=find(y);
    49         }
    50     }
    51 }
    52 int main()
    53 {
    54     scanf("%d",&T);
    55     while(T--)
    56     {
    57         scanf("%d%d",&n,&m);
    58         zz1=0,zz2=0;
    59         for(int i=1;i<=n;i++) fa[i]=i,a1[i]=a2[i]=0;
    60         for(int i=1;i<=m;i++)
    61         {
    62             int x,y;
    63             scanf("%d%d",&x,&y);
    64             x++,y++;
    65             build1(x,y);
    66             build1(y,x);
    67         }
    68         scanf("%d",&Q);
    69         cnt=0;
    70         for(int i=1;i<=Q;i++)
    71         {
    72             int x;
    73             scanf("%d",&x);x++;
    74             if(find(x)!=x)continue;
    75             dfs(x);
    76             a2[x]=0;
    77             for(int j=1;j<=cnt;j++)
    78             {
    79                 fw[tmp[j]]=0;
    80                 build2(x,tmp[j]);
    81                 fa[tmp[j]]=x;
    82             }
    83             cnt=0;
    84         }
    85         for(int i=1;i<=n;i++)
    86         {
    87             printf("%d ",find(i)-1);
    88         }
    89         printf("
    ");
    90     }
    91     return 0;
    92 }
    View Code
  • 相关阅读:
    垃圾回收app冲击(一)
    本篇看似是一篇拍马屁的博客!但是真情实感!
    搜索建议
    冲击团队项目需求分析
    疫情分析冲击(五)
    疫情分析冲击(四)
    疫情分析冲击(三)
    疫情分析冲击(二)
    垃圾分类网站
    Android学习——singleInstance
  • 原文地址:https://www.cnblogs.com/liutianrui/p/13338802.html
Copyright © 2011-2022 走看看