• Connected Components? Codeforces


    https://codeforces.com/contest/920/problem/E

    https://www.luogu.org/problemnew/show/P3452

    https://www.lydsy.com/JudgeOnline/problem.php?id=1098

    CF貌似出了原题?

    这几个都是一样的,输入输出都一样,就是读入一张图,要求补图的连通块个数以及各个连通块大小

    可以这样搞:维护一个set表示所有当前没到过的点;一开始所有点加进去

    取出set中任意点作为起始点并从set中删除,以此为起点进行bfs,直到set为空;则同一次bfs中经过的点是同一个连通块内的

    从某个点u开始bfs的时候,就先找出所有原图中与u有边的点v,如果set中还有v就从set中暂时删掉v(记录下哪一些是实际删掉的)

    然后当前set中所有点都是u能到达的,暴力加入bfs的队列并从set中删除;处理完这个u后,再向set中加回前面暂时删掉的点

    set可以换成链表。。就O(n+m)了

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 #include<list>
     6 #include<queue>
     7 using namespace std;
     8 #define fi first
     9 #define se second
    10 #define mp make_pair
    11 #define pb push_back
    12 typedef long long ll;
    13 typedef unsigned long long ull;
    14 typedef pair<int,int> pii;
    15 struct E
    16 {
    17     int to,nxt;
    18 }e[4000100];
    19 int f1[200100],ne;
    20 list<int> li;
    21 list<int>::iterator it[200100];
    22 queue<int> q;
    23 int n,m;
    24 int tt[200100];
    25 int an[200100];
    26 int main()
    27 {
    28     int i,a,b,t,u,sz,k;
    29     list<int>::iterator i1;
    30     scanf("%d%d",&n,&m);
    31     for(i=1;i<=m;i++)
    32     {
    33         scanf("%d%d",&a,&b);
    34         e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne;
    35         e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne;
    36     }
    37     for(i=1;i<=n;i++)    it[i]=li.insert(li.end(),i);
    38     while(!li.empty())
    39     {
    40         t=li.front();li.erase(it[t]);it[t]=li.end();
    41         sz=0;
    42         q.push(t);
    43         while(!q.empty())
    44         {
    45             u=q.front();q.pop();
    46             sz++;
    47             tt[0]=0;
    48             for(k=f1[u];k;k=e[k].nxt)
    49                 if(it[e[k].to]!=li.end())
    50                 {
    51                     tt[++tt[0]]=e[k].to;
    52                     li.erase(it[e[k].to]);
    53                     it[e[k].to]=li.end();
    54                 }
    55             while(!li.empty())
    56             {
    57                 t=li.front();li.erase(it[t]);it[t]=li.end();
    58                 q.push(t);
    59             }
    60             for(i=1;i<=tt[0];i++)    it[tt[i]]=li.insert(li.end(),tt[i]);
    61         }
    62         an[++an[0]]=sz;
    63     }
    64     sort(an+1,an+an[0]+1);
    65     printf("%d
    ",an[0]);
    66     for(i=1;i<=an[0];i++)    printf("%d ",an[i]);
    67     return 0;
    68 }
    View Code

    好像也可以改成bfs到点u时,就枚举当前set中剩余的所有点v,然后判断(u,v)是否存在于原图中,如果答案为否则将v加入队列,如果用哈希表判断边是否存在则复杂度仍然O(n+m)

  • 相关阅读:
    来自1068
    耻辱的时间戳(笑哭)
    依然排序
    呵呵
    好吧,第二篇
    来自机房的第一篇博客
    Shader-水流效果
    unity中虚拟摇杆的实现
    (转载)Unity3d中的属性(Attributes)整理
    C#冒泡排序法及优化
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9656551.html
Copyright © 2020-2023  润新知