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.\n",x);
 96             else
 97                 printf("Red Alert: City %d is lost!\n",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.\n");
106     }
107     return 0;
108 }

 

posted @ 2020-03-27 14:41  kongbursi  阅读(310)  评论(0编辑  收藏  举报