牛客多校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\n",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\n",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 }

 

上一篇:目标跟踪之Camshift


下一篇:应收单表头数据校验