• PAT甲级1013题解——并查集+路径压缩


    题目分析:

    本题初步浏览题目就知道是并查集的模板题,数据输入范围N为1~1000,则M的范围为0~1000^2,通过结构体记录每一对连线的关系,p[]数组记录每个节点的跟,对于k次查询,每次都要重新维护p[]数组,而每次的区别在于都要排除被占领的节点重新维护p[]数组的节点的链接关系,而最终的答案就是集合数-2(占领点一定是单独的集合,n个集合需要n-1条边就能相连)

     1 #include<iostream>
     2 using namespace std;
     3 
     4 struct Node{
     5     int from;
     6     int to;
     7 }a[1000005];
     8 int p[1005];
     9 int n, m, k;
    10 
    11 int find(int x){
    12     int y = x;
    13     while(p[x] != x){
    14         x = p[x];
    15     }
    16     //路径压缩 此时x是根 
    17     while(p[y] != x){
    18         int t = y;            //对于路径上的每个y节点都要保留一下 
    19         y = p[y];            //此时我们还是按照上述的顺序去查询根 
    20         p[t] = x;            //y已经变的p[y]的值,而t则记录了之前y的值 而p[之前的y]已经用不到了,我们将其路径压缩,把它的跟直接变为x 
    21     }
    22     return x;
    23 }
    24 
    25 void Union(int x, int y){
    26     int fx = find(x);
    27     int fy = find(y);
    28     if(fx != fy){
    29         p[fx] = fy;
    30     }    
    31 }
    32 
    33 void init(int occupy){
    34     for(int i = 1; i <= n; i++) p[i] = i;
    35     for(int i = 1; i <= m; i++){
    36         //根据a中的一对一对的关系维护并查集 同时注意被占领的城市不参与其中
    37         if(a[i].from != occupy && a[i].to != occupy){
    38             Union(a[i].from, a[i].to);
    39         }
    40     }
    41 }
    42 
    43 void run(){
    44     int ans = 0;
    45     for(int i = 1; i <= n; i++){
    46         if(p[i] == i){
    47             ans++;
    48         }
    49     }    
    50     printf("%d
    ", ans - 2);
    51 } 
    52 
    53 int main(){
    54     while(scanf("%d%d%d", &n, &m, &k) != EOF){
    55         for(int i = 1; i <= m; i++){
    56             scanf("%d%d", &a[i].from, &a[i].to);            
    57         }
    58         int occupy; 
    59         for(int i = 1; i <= k; i++){
    60             scanf("%d", &occupy);
    61             //每次都要初始化并查集 
    62             init(occupy);
    63             //获取每次至少要添加的线条数 
    64             run();
    65         }
    66     }
    67     return 0;
    68 }
    如果有任何意见请在评论区积极留言
  • 相关阅读:
    Linux curl命令详解
    php技能树---大神的进阶之路
    PHP Socket 编程之9个主要函数的使用之测试案例
    史上最全的PHP正则表达式
    php 简单使用redis 队列示例
    PHP中使用 Memcached 的测试案例
    机动车驾驶(1)--- 禁令标志汇总 by John
    闵可夫斯基和(Mincowsky sum)
    二维平面上判断点是否在三角形内
    计算任意多边形的面积
  • 原文地址:https://www.cnblogs.com/YLTFY1998/p/11666697.html
Copyright © 2020-2023  润新知