zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校第三场G-Operating on a Graph(并查集+list)

    题目大意:给你n个点,m条边,现在有q次操作,每次一个x,表示将与x所连的所有点归并到x团里面,问最后每个点属于哪个团。

    输入

    5
    4 3
    0 1
    1 2
    2 3
    4
    0 1 3 0
    4 3
    0 1
    1 2
    2 3
    2
    0 2
    4 3
    0 1
    1 2
    2 3
    2
    0 3
    4 1
    1 3
    1
    2
    5 5
    0 1
    0 2
    1 2
    1 3
    3 4
    3
    4 4 0

    输出

    0 0 0 0
    2 2 2 2
    0 0 3 3
    0 1 2 3
    0 0 0 0 0

    看见团和合并之类的,很容易联想到并查集,每次合并的时候我们将每个点的祖宗设置为x就好了(注意,如果x的祖宗不是自己的话就说明它已经被合并了,这个x团中就是空的,我们直接跳过)。接下来就是将两个祖宗团的所有点合并了,我们需要用一个数据结构来实现这种操作,而list应该是一个比较理想的容器,它的splice方法是比较高效的

    以下是AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int mac=1e6+10;
    
    struct Edge
    {
        int to,next;
    }eg[mac<<1];
    int head[mac],father[mac],num=0;
    list<int>group[mac];
    bool vis[mac];
    
    void add(int u,int v)
    {
        eg[++num]=Edge{v,head[u]};
        head[u]=num;
    }
    
    int find(int x){return x==father[x]?x:father[x]=find(father[x]);}
    
    void unions(int u,int v)
    {
        int fu=find(u),fv=find(v);
        if (fu!=fv){
            father[fu]=fv;
            group[fv].splice(group[fv].end(),group[fu]);
        }
    }
    
    int main(int argc, char const *argv[])
    {
        int t,n,m;
        scanf ("%d",&t);
        while (t--){
            scanf ("%d%d",&n,&m);
            num=0;
            for (int i=0; i<n+10; i++){
                head[i]=-1;father[i]=i;
                vis[i]=0; group[i].clear();
                group[i].push_back(i);
            }
            for (int i=1; i<=m; i++){
                int u,v;
                scanf ("%d%d",&u,&v);
                add(u,v);add(v,u);
            }
            int q;
            scanf ("%d",&q);
            while (q--){
                int x;
                scanf ("%d",&x);
                int gkd=find(x);
                if (gkd!=x) continue;
                int len=group[x].size();
                for (int i=0; i<len; i++){//!!注意这里不能用size。
                    int u=group[x].front();
                    for (int j=head[u]; j!=-1; j=eg[j].next){
                        int v=eg[j].to;
                        unions(v,x);
                        if (vis[v]) continue;
                        group[x].push_back(v);
                        vis[v]=1;
                    }
                    group[x].pop_front();
                }
            }
            for (int i=0; i<n; i++)
                printf("%d ",find(i));
            printf("
    ");
        }
        return 0;
    }
    路漫漫兮
  • 相关阅读:
    分享5款不同的多级导航切换DIV的jQuery特效
    CSS3+JS制作的一款图标任意拖动,并且可以放在文件夹中
    一款jQuery图片浏览插件可简单的设置7种切换效果
    基于HTML5和CSS的焦点图全屏切换的炫酷特效
    一款基于jQuery有趣的眼睛随鼠标进行有磁性的旋转
    jQuery+CSS3打造的3款不同的3D焦点图切换jQuery特效
    Maven Nexus仓库管理器
    Spring Basics
    补昨天的日志
    又一星期的星期一
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/13353639.html
Copyright © 2011-2022 走看看