zoukankan      html  css  js  c++  java
  • 并查集,动态连通性

    http://acm.csu.edu.cn/OnlineJudge/problem.php?cid=2079&pid=1

    n,m代码n个点,m条边

    随之而来m条边

    q 代表q个操作

    q行,每行一个序号,代表将第m个输入的边删除,问删除后有多少个连通块。

    思路:我们将m条边,和q询问记录下来,并将要删除的边标记。

    然后对那些不用的边使用并查集,并算出有多少个连通块。

    然后从最后一个询问开始,依次将那些边加入并查集,如果加入时,两个点的父亲不同,那么连通块就减少一个

     1 #include <stdio.h> 
     2 #include <string.h> 
     3 #include <stdlib.h> 
     4 #include <algorithm> 
     5 #include <iostream> 
     6 #include <queue> 
     7 #include <stack> 
     8 #include <vector> 
     9 #include <map> 
    10 #include <set> 
    11 #include <string> 
    12 #include <math.h> 
    13 using namespace std;
    14 #pragma warning(disable:4996) 
    15 typedef long long LL;
    16 const int INF = 1 << 30;
    17 const int N = 100000 + 10;
    18 int u[N], v[N], q[N];
    19 int father[N];
    20 int ans[N];
    21 bool vis[N];
    22 void init(int n)
    23 {
    24     for (int i = 0; i <= n; ++i)
    25         father[i] = i;
    26     memset(vis, 0, sizeof(vis));
    27 }
    28 int find(int x)
    29 {
    30     if (x == father[x])
    31         return x;
    32     return father[x] = find(father[x]);
    33 }
    34 int main()
    35 {
    36     int n, m, i, Q;
    37     while (scanf("%d%d", &n, &m) != EOF)
    38     {
    39         init(n);
    40         for (i = 1; i <= m; ++i)
    41         {
    42             scanf("%d%d", &u[i], &v[i]);
    43         }
    44         scanf("%d", &Q);
    45         for (i = 0; i < Q; ++i)
    46         {
    47             scanf("%d", &q[i]);
    48             vis[q[i]] = true;
    49         }
    50         for (i = 1; i <= m; ++i)
    51         {
    52             if (!vis[i])
    53             {
    54                 int rx = find(u[i]);
    55                 int ry = find(v[i]);
    56                 if (rx != ry)
    57                     father[rx] = ry;
    58             }
    59         }
    60         int tmp = 0;
    61         for (i = 1; i <= n; ++i)
    62         if (father[i] == i)//算出连通块
    63             tmp++;
    64         for (i = Q - 1; i >= 0; --i)//从后往前,加入那些要删除的边
    65         {
    66             int rx = find(u[q[i]]);
    67             int ry = find(v[q[i]]);
    68             ans[i] = tmp;//
    69             if (rx != ry)
    70             {
    71                 father[rx] = ry;
    72                 tmp--;
    73             }
    74 
    75         }
    76         for (i = 0; i < Q; ++i)
    77             i == Q - 1 ? printf("%d
    ", ans[i]) : printf("%d ", ans[i]);
    78     }
    79 }
    View Code
  • 相关阅读:
    【LeetCode】Hash
    【LeetCode】Heap
    【LeetCode】Stack
    【CodeVS】 纯OI题
    【LeetCode】String
    【LeetCode】Array
    WinForm窗体 常用属性
    C# ADO.NET 实体类中的属性扩展
    C# ADO.NET 三层架构
    C# ADO.NET 数据库的安全(sql 字符串注入攻击、使用占位符防止注入攻击)
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4474620.html
Copyright © 2011-2022 走看看