zoukankan      html  css  js  c++  java
  • 牛客多校3-Operating on a Graph【dsu】

    题意:

      给定n个点m条边的无向图,每个点一开始代表一种集合,共有n个集合

      之后给出q次操作,每次询问将指定一个集合Oi,将所有与该集合有相连边的其他集合并入集合Oi

      问经过q次操作后所有点属于哪个集合

    做法:

      之前没怎么遇见过启发式合并的题,所以赛时做法只是遍历所有点

      每次从搜到的指定集合中的点开始dfs搜子树来合并。

      这种做法会导致超时和在dfs找并查集子树时内存超限。

      赛后了解到这就是启发式合并的基本思想,小集合并入大集合中

      每次直接对集合进行操作,然后把小集合拼接在大集合上

      基本上就是个启发式合并的板子题了

    CODE

      1 #include <bits/stdc++.h>
      2 #define dbg(x) cout << #x << "=" << x << endl
      3 #define eps 1e-8
      4 #define pi acos(-1.0)
      5 
      6 using namespace std;
      7 typedef long long LL;
      8 
      9 const int inf = 0x3f3f3f3f;
     10 
     11 template<class T>inline void read(T &res)
     12 {
     13     char c;T flag=1;
     14     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
     15     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
     16 }
     17 
     18 namespace _buff {
     19     const size_t BUFF = 1 << 19;
     20     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
     21     char getc() {
     22         if (ib == ie) {
     23             ib = ibuf;
     24             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
     25         }
     26         return ib == ie ? -1 : *ib++;
     27     }
     28 }
     29 
     30 int qread() {
     31     using namespace _buff;
     32     int ret = 0;
     33     bool pos = true;
     34     char c = getc();
     35     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
     36         assert(~c);
     37     }
     38     if (c == '-') {
     39         pos = false;
     40         c = getc();
     41     }
     42     for (; c >= '0' && c <= '9'; c = getc()) {
     43         ret = (ret << 3) + (ret << 1) + (c ^ 48);
     44     }
     45     return pos ? ret : -ret;
     46 }
     47 
     48 const int maxn = 8e5 + 7;
     49 
     50 int t;
     51 int n;
     52 int fa[maxn];
     53 int m;
     54 
     55 int fid(int x) {
     56     return x == fa[x] ? x : fa[x] = fid(fa[x]);
     57 }
     58 
     59 // vector<int> g[maxn];
     60 
     61 // void dfs(int x, int pre, int oo) {
     62 //     if(head[x] > cnt || fa[fid(x)] != oo) {
     63 //         return;
     64 //     }
     65 //     for ( int i = head[x]; i; i = nxt[i] ) {
     66 //         int v = edge[i];
     67 //         if(v == pre || fa[fid(x)] != oo) {
     68 //             continue;
     69 //         }
     70 //         if(fa[v] == fa[x]) {
     71 //             for(auto it : g[v]) {
     72 //                 dfs(it, v, oo);
     73 //             }
     74 //         }
     75 //         else {
     76             
     77 //             int fidu = fid(x), fidv = fid(v);
     78 //             //printf("fa[%d]:%d fa[%d]:%d
    ",x, fidu, fidv, fidv);
     79 //             if(fidu != oo)
     80 //                 continue;
     81 //             fa[fidv] = fidu;
     82 //             for(auto it : g[fidv]) {
     83 //                 g[fidu].push_back(it);
     84 //             }
     85 //             //printf("2:fa[%d]:%d fa[%d]:%d
    ",x, fa[fidu], fidv, fa[fidv]);
     86 //             //return;
     87 //         }
     88 //     }
     89 // }
     90 
     91 vector<int> g[maxn];
     92 
     93 void merge(vector<int> & a, vector<int> & b)
     94 {
     95     if (a.size() < b.size()) swap(a, b);
     96     for (auto & x: b) a.push_back(x);
     97 }
     98 
     99 
    100 int main()
    101 {
    102     scanf("%d",&t);
    103     while(t--) {
    104         scanf("%d %d",&n, &m);
    105         int maxx = max(n, m);
    106         for ( int i = 0; i <= maxx; ++i ) {
    107             fa[i] = i;
    108             g[i].clear();
    109         }
    110         for ( int i = 1; i <= m; ++i ) {
    111             int u,v;
    112             scanf("%d %d",&u, &v);
    113             g[u].push_back(v);
    114             g[v].push_back(u);
    115         }
    116         int q;
    117         scanf("%d",&q);
    118         while (q--) {
    119             int x;
    120             scanf("%d", &x);
    121             if (fid(x) != x) continue;
    122             vector<int> tmp = g[x];
    123             g[x].clear();
    124             for (auto & v: tmp) {
    125                 int u = fid(v);
    126                 if (fid(u) == fid(x)) continue;
    127                 merge(g[x], g[u]);
    128                 fa[fid(u)] = fid(x);
    129             }
    130         }
    131         // for ( int i = 0; i <= n - 1; ++i ) {
    132         //     for(auto it : g[i]) {
    133         //         cout << it << ' ';
    134         //     }
    135         //     puts("");
    136         // }
    137         for ( int i = 0; i <= n - 1; ++i ) {
    138                 printf("%d ",fid(i));
    139         }
    140         puts("");
    141     }    
    142     return 0;
    143 }
  • 相关阅读:
    MVC 中创建自己的异常处理
    ajax 跨域解决方法
    值传递,引用传递
    值类型,引用类型 结合 栈,堆的理解
    SQL中 ALL 和 ANY 区别的
    SQL中的逻辑运算符
    使用函数输出两个数的最大值
    九句话,送给正在奋斗的我们,每天读一遍
    C语言函数调用简简介
    优秀项目经理的七个习惯
  • 原文地址:https://www.cnblogs.com/orangeko/p/13368546.html
Copyright © 2011-2022 走看看