天梯赛练习——7-37 红色警报 (25分)(并查集)

题目:

在这里插入图片描述

分析:

该题使用并查集来解决,通过判断去除 某一个城市 之前和之后的连通性得出是否要发出警报
每一次攻占某一个城市之前,求出根节点的个数ans,攻占城市之后,标记该城市,然后对未标记的城市做一遍并查集,判断此时的根节点一共有cnt个,如果 cnt 等于 ans ,说明此时破坏的城市并没有使连通性发生变化,如果cnt <ans说明,此时破坏的城市为孤立城市,也不会发出警报,在cnt > ans 说明破坏了原有的连通性,需要发出警报。

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

const int MAXN = 505;
int root[MAXN],n,m,k,ans;
bool vis[MAXN];

struct node
{
    int x,y;
}no[5005];

int getr(int x)
{
    if(root[x] == x) return x;
    else return root[x] = getr(root[x]);
}

void Union(int x,int y)
{
    int xx = getr(x);
    int yy = getr(y);
    if(xx != yy)
        root[xx] = yy;
}

int main()
{
    int city;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;++i)
        root[i] = i;
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d",&no[i].x,&no[i].y);
        Union(no[i].x,no[i].y);
    }
    for(int i=0;i<n;++i)
        if(root[i]==i) ans++;
    scanf("%d",&k);
    while(k--)
    {
        int cnt = 0;
        scanf("%d",&city);
        vis[city] = true;
        for(int i=0;i<n;++i)
            root[i] = i;
        for(int i=1;i<=m;++i)
            if(!vis[no[i].x] && !vis[no[i].y])
                Union(no[i].x,no[i].y);
        for(int i=0;i<n;++i)
            if(!vis[i]&&root[i]==i) cnt++;
        if(cnt <= ans)
            printf("City %d is lost.\n",city);
        else
            printf("Red Alert: City %d is lost!\n",city);
        ans = cnt;
        if(ans == 0)
        {
            printf("Game Over.\n");
            return 0;
        }
    }
    return 0;
}

发布了61 篇原创文章 · 获赞 7 · 访问量 3614

猜你喜欢

转载自blog.csdn.net/weixin_42469716/article/details/105275157
今日推荐