红色警报 并查集

#include <bits/stdc++.h>
using namespace std;
const int maxn=501,maxsize=5001;
int father[maxn];
bool visited[maxn]={false};//表示该城市是否被攻占
struct Edge
{
       int u;
       int v;
};
struct Edge edge[maxsize];
int findfather(int x)
{
     if(x==father[x])
              return x;
     else
     {
        int F=findfather(father[x]);//递归找父亲
        father[x]=F;//由低到高 分别把f赋给每一个人
        return F;

     }
}
void Union(int a,int b)
{
    int fa=findfather(a);
    int fb=findfather(b);
    if(fa!=fb)
        father[fa]=fb;

}
int main()
{
    int n,m,k,num1=0,num2=0;
    cin>>n>>m;
    for(int i=0;i<n;++i)
       father[i]=i;
    for(int i=0;i<m;++i)
    {
       cin>>edge[i].u>>edge[i].v;
       Union(edge[i].u,edge[i].v);

    }
    for(int i=0;i<n;++i)
    {
      if(father[i]==i)
      {
          num1++;
      }
    }
    cin>>k;
    int cnt=k;
    while(k--)
    {
       num2=0;
       int city;
       cin>>city;
       visited[city]=true;//排除这个点重新建立新的并查集
           for(int i=0;i<n;++i)
              father[i]=i;
       for(int i=0;i<m;++i)//重新建立并查集
       {
           if(visited[edge[i].u]==true||visited[edge[i].v]==true)//只要两个连通的城市有一个已经被干掉 就跳过
           {
              continue;
           }
           Union(edge[i].u,edge[i].v);
       }
      for(int i=0;i<n;++i)//重新数一下有多少个连通块 去掉之前攻占的
       {
           if(visited[i]==false&&father[i]==i)//由于还是会访问之前被攻占城市所以要去除
                     num2++;

       }
       if(num2==num1||num2==num1-1)//连通块不变或者说连通块少一个没有影响
       {
              printf("City %d is lost.\n",city);
              num1=num2;
       }
       else if(num2>num1)
       {
            printf("Red Alert: City %d is lost!\n",city);
            num1=num2;
       }
    }
       if(cnt==n)
       {
          printf("Game Over.\n");
       }



    return 0;
}

 

上一篇:leetcode 1107


下一篇:处理缺失值