• L2-013 红色警报 (25分) 并查集复杂度


    代码:

      1 /*
      2 这道题也是简单并查集,并查集复杂度:
      3 空间复杂度为O(N),建立一个集合的时间复杂度为O(1),N次合并M查找的时间复杂度为O(M Alpha(N)),
      4 这里Alpha是Ackerman函数的某个反函数,在很大的范围内(人类目前观测到的宇宙范围估算有10的80次方个原子,
      5 这小于前面所说的范围)这个函数的值可以看成是不大于4的,所以并查集的操作可以看作是线性的。
      6 
      7 不弄清楚一个算法的复杂度就是不敢很用
      8 
      9 
     10 题解:
     11 在询问时,标记当前结点,然后将其余的结点并查集一次,求出集合数,
     12 如果集合数相等或者前面完整结点的集合数+1=当前集合数,那么也就说明了去掉当前结点是没什么影响的,
     13 其余情况就是有影响
     14 
     15 思路很好想,了解了复杂度之后就敢下手了
     16 
     17 解释一下下面内容:
     18 1、集合数相等为什么说明了去掉当前结点是没什么影响
     19 当你标记一个点之后,在进行并查集这个时候肯定会把这个点孤立出来,也就是多了一个只有这一个点的集合
     20 如果在原图中这个点就被孤立,那么标记之后还是相当于孤立,那么这个时候去掉当前结点是没什么影响
     21 
     22 2、前面完整结点的集合数+1=当前集合数时为什么说明了去掉当前结点是没什么影响
     23 如果这个点原本并不在原图中孤立,那么如果标记这个点之后,如果这个点去掉不会造成影响,那么标记这个点之后的集合数要比
     24 之前的大1
     25 */
     26 #include<stdio.h>
     27 #include<string.h>
     28 #include<iostream>
     29 #include<algorithm>
     30 #include<queue>
     31 using namespace std;
     32 const int maxn=505;
     33 int n,m;
     34 struct node
     35 {
     36     int u,v;
     37 } e[5005];
     38 int vist[550],fa[550];
     39 int Find(int x)
     40 {
     41     return x==fa[x]?fa[x]:Find(fa[x]);
     42 }
     43 void Union(int x,int y)
     44 {
     45     int xc=Find(x);
     46     int yc=Find(y);
     47     if(xc!=yc)
     48     {
     49         fa[xc]=yc;
     50     }
     51 }
     52 int main()
     53 {
     54     int k;
     55     int u,v;
     56     while(scanf("%d%d",&n,&m)!=EOF)
     57     {
     58         for(int i=0; i<n; i++)
     59             fa[i]=i;
     60         for(int i=0; i<m; i++)
     61         {
     62             scanf("%d%d",&u,&v);
     63             e[i].u=u,e[i].v=v;
     64             Union(u,v);
     65         }
     66         int num=0,num1;
     67         for(int i=0; i<n; i++)
     68         {
     69             if(fa[i]==i)
     70             {
     71                 num++;
     72             }
     73         }
     74         memset(vist,0,sizeof(vist));
     75         scanf("%d",&k);
     76         while(k--)
     77         {
     78             num1=0;
     79             for(int i=0;i<n;i++)
     80                 fa[i]=i;
     81             int x;
     82             scanf("%d",&x);
     83             vist[x]=1;
     84             for(int i=0;i<m;i++)
     85             {
     86                 if(vist[e[i].u]==1||vist[e[i].v]==1)
     87                 continue;
     88                 else
     89                     Union(e[i].u,e[i].v);
     90             }
     91             for(int i=0;i<n;i++)
     92                 if(fa[i]==i)
     93                 num1++;
     94             if(num==num1||num+1==num1)
     95             printf("City %d is lost.
    ",x);
     96             else
     97                 printf("Red Alert: City %d is lost!
    ",x);
     98             num=num1;
     99         }
    100         num=0;
    101         for(int i=0;i<n;i++)
    102             if(vist[i]==1)
    103             num++;
    104         if(num==n)
    105             printf("Game Over.
    ");
    106     }
    107     return 0;
    108 }
  • 相关阅读:
    hdu5247找连续数(打表)
    hdu5246超级赛亚ACMer
    hdu5246超级赛亚ACMer
    cf534D 枚举握手次数
    cf534D 枚举握手次数
    4467奇妙的方式优化暴力的01边查询
    4467奇妙的方式优化暴力的01边查询
    POJ1364基本的查分约束问题
    POJ1364基本的查分约束问题
    poj1509最小表示法
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/12581341.html
Copyright © 2020-2023  润新知