zoukankan      html  css  js  c++  java
  • ICPC Central Europe Regional Contest 2019-I-Saba1000kg

    题目传送门

    sol:因为查询的点一共最多只有$100000$个。若当本次查询的点比较少,小于$sqrt{100000}$,那我们可以枚举起始点$u$和终点$v$,若$u, v$之间有边,则用并查集将$u, v$节点合并,最后统计有多少个联通块;若当本次查询的点比较多,大于$sqrt{100000}$,那我们可以枚举所有边,若$u, v$都在本次查询的点集内,则用并查集将$u, v$节点合并,最后统计有多少个联通块。

    • 二分+并查集
      #include <bits/stdc++.h>
      using namespace std;
      typedef long long LL;
      typedef pair<int, int> PII;
      const int MAXN = 100010;
      inline int read() {
          int n = 0, f = 1; char c = getchar();
          while (c < '0' || c > '9') {
              if (c == '-') f = -f;
              c = getchar();
          }
          while (c >= '0' && c <= '9') {
              n = 10 * n + (c ^ '0');
              c = getchar();
          }
          return f * n;
      }
      vector<int> edge[MAXN];
      int node[MAXN], dsu[MAXN];
      int find(int i) {
          if (dsu[i] == -1) return i;
          return dsu[i] = find(dsu[i]);
      }
      bool search_1(int u, int v) {
          int l = -1, r = edge[u].size();
          while (l < r - 1) {
              int m = l + r >> 1;
              if (edge[u][m] == v) return true;
              if (edge[u][m] < v) l = m;
              if (edge[u][m] > v) r = m;
          }
          return false;
      }
      bool search_2(int l, int r, int k) {
          if (node[l] == k || node[r] == k) return true;
          while (l < r - 1) {
              int m = l + r >> 1;
              if (node[m] == k) return true;
              if (node[m] < k) l = m;
              if (node[m] > k) r = m;
          }
          return false;
      }
      void slove_1(int n, int k) {
          for (int i = 1; i <= k; i++) {
              for (int j = 1; j < i; j++) {
                  if (search_1(node[i], node[j])) {
                      int fu = find(node[i]);
                      int fv = find(node[j]);
                      if (fu != fv) dsu[fu] = fv;
                  }
              }
          }
          int ans = 0;
          for (int i = 1; i <= k; i++) {
              if (dsu[node[i]] == -1) ans ++;
              else dsu[node[i]] = -1;
          }
          printf("%d
      ", ans);
      }
      int slove_2(int n, int k) {
          for (int u = 1; u <= n; u++) {
              for (int v : edge[u]) {
                  if (search_2(1, k, u) && search_2(1, k, v)) {
                      int fu = find(u);
                      int fv = find(v);
                      if (fu != fv) dsu[fu] = fv;
                  }
              }
          }
          int ans = 0;
          for (int i = 1; i <= k; i++) {
              if (dsu[node[i]] == -1) ans ++;
              else dsu[node[i]] = -1;
          }
          printf("%d
      ", ans);
      }
      int main() {
          int n = read(), m = read(), q = read();
          for (int i = 1; i <= m; i++) {
              int u = read(), v = read();
              edge[u].push_back(v);
              edge[v].push_back(u);
          }
          for (int i = 1; i <= n; i++) {
              sort(edge[i].begin(), edge[i].end());
          }
          memset(dsu, -1, sizeof(dsu));
          while (q--) {
              int k = read();
              for (int i = 1; i <= k; i++) node[i] = read();
              sort(node + 1, node + 1 + k);
              if (k <= 320) slove_1(n, k);
              else slove_2(n, k);
          }
          return 0;
      }

      ------------------------------------------------------------分隔线------------------------------------------------------------

      总结:这道题的解法真妙,一道题里用到了两种不同策略。$solve1$的复杂度是$O(k^2log_2k)$,当k比较小时非常快,$slove2$的复杂度是$O(mlog_2k)$,随着$k$的增加变化不大。所以$k$小用$slove1$,$k$大用$slove2$。

  • 相关阅读:
    windows 按时自动化任务
    Linux libusb 安装及简单使用
    Linux 交换eth0和eth1
    I.MX6 GPS JNI HAL register init hacking
    I.MX6 Android mmm convenient to use
    I.MX6 GPS Android HAL Framework 调试
    Android GPS GPSBasics project hacking
    Python windows serial
    【JAVA】别特注意,POI中getLastRowNum() 和getLastCellNum()的区别
    freemarker跳出循环
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/12911549.html
Copyright © 2011-2022 走看看