L2-013 红色警报 (25 分)

L2-013 红色警报 (25 分)

战争中保持各个城市间的连通性非常重要。本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报。注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不改变其他城市之间的连通性,则不要发出警报。

输入格式:

输入在第一行给出两个整数N(0 < N ≤ 500)和M(≤ 5000),分别为城市个数(于是默认城市从0到N-1编号)和连接两城市的通路条数。随后M行,每行给出一条通路所连接的两个城市的编号,其间以1个空格分隔。在城市信息之后给出被攻占的信息,即一个正整数K和随后的K个被攻占的城市的编号。

注意:输入保证给出的被攻占的城市编号都是合法的且无重复,但并不保证给出的通路没有重复。

输出格式:

对每个被攻占的城市,如果它会改变整个国家的连通性,则输出Red Alert: City k is lost!,其中k是该城市的编号;否则只输出City k is lost.即可。如果该国失去了最后一个城市,则增加一行输出Game Over.

输入样例:

5 4
0 1
1 3
3 0
0 4
5
1 2 0 4 3

输出样例:

City 1 is lost.
City 2 is lost.
Red Alert: City 0 is lost!
City 4 is lost.
City 3 is lost.
Game Over.

 

 

去年大二参加天梯赛之前刷这道题的时候感觉好难啊,现在马上又快比赛了,翻回头看这道题感觉好水啊,可能是思维上来了吧,瞬间就能想很多。

这道题我想了有俩种做法,一种是并查集,一种是搜索。俩种做法本质都是一样的用来判断图的连通性。

这道题说了那么多,转换下思路不就是考的是图的连通性吗?

用搜索的话,其实就是搜有几个独立的图,然后比较被攻占的城市后独立的图增加了多少个,我们用邻接表标记一下互通,在用flag数组标记搜索过程中这个点被找没找过。

dfs做法如下:

# include <iostream>
# include <cmath>
# include <cstring>
# include <string>
# include <map>
# include <algorithm>
# include <vector>
# include <cstdio>
# include <string>
# include <queue>

using namespace std;
const int maxn = 505;
int book[maxn][maxn];
int flag[maxn];
int n, m;

void dfs(int x)
{
    for(int i = 0; i < n; i++)
    {
        if(!flag[i] && book[x][i])
        {
            flag[i] = true;
            dfs(i);
        }
    }
}

int counting()
{
    memset(flag, false, sizeof(flag));
    int cnt = 0;
    for(int i = 0; i < n; i++)
    {
        if(!flag[i])
        {
            flag[i] = true;
            dfs(i);
            cnt++;
        }
    }
    return cnt;
}
int main(int argc, char *argv[])
{
    cin >> n >> m;
    for(int i = 0; i < m; i++)
    {
        int x, y;
        cin >> x >> y;
        book[x][y] = 1;
        book[y][x] = 1;
    }

    int k;
    cin >> k;
    int cnt = counting();
    for(int i = 0; i < k; i++)
    {
        int attick;
        cin >> attick;
        for(int j = 0; j < n; j++)
        {
            book[attick][j] = 0;
            book[j][attick] = 0;
        }
        int c = counting();
        if(c > cnt + 1)
        {
            cout <<"Red Alert: City "<< attick<<" is lost!" << endl;
        }
        else
        {
            cout << "City "<< attick<<" is lost."<< endl;
        }
        cnt = c;
        if(i == n -1)
        {
            cout << "Game Over." << endl;
        }
    }
    return 0;
}


并查集也是一样的思路,只不过我想的是并没被攻占的城市,然后攻占后在重新并一下,比较下少了几个城市就可以。

# include <iostream>
# include <cmath>
# include <cstring>
# include <string>
# include <map>
# include <algorithm>
# include <vector>
# include <cstdio>
# include <string>
# include <queue>

using namespace std;
const int maxn = 5005;
int pre[maxn];
int flag[maxn];
int n, m;

struct node
{
    int x, y;
}s[maxn];

void fun()
{

    for(int i = 0; i < maxn; i++)
    {
        pre[i] = i;
    }
}

int find(int x)
{
    if(pre[x] != x)
    {
        pre[x] = find(pre[x]);
    }
    return pre[x];
}

void join(int x, int y)
{
    int tx = find(x);
    int ty = find(y);
    if(tx != ty)
    {
        pre[ty] = tx;
    }
}

int main(int argc, char *argv[])
{
    fun();
    memset(s, false, sizeof(s));
    memset(flag, false, sizeof(flag));
    cin >> n >> m;
    for(int i = 0; i < m; i++)
    {
        cin >> s[i].x >> s[i].y;
        join(s[i].x, s[i].y);
    }
    int k;
    cin >> k;
    int cnt = 0;
    for(int i = 0; i < n; i++)
    {
        if(pre[i] == i && !flag[i])
        {
            cnt++;
        }
    }
    for(int i = 0; i < k; i++)
    {
        fun();
        int attick;
        cin >> attick;
        flag[attick] = 1;
        for(int j = 0; j < m; j++)
        {
            if(!flag[s[j].x] && !flag[s[j].y])
                join(s[j].x, s[j].y);
        }
        int c = 0;
        for(int p = 0; p < n; p++)
        {
            if(pre[p] == p && !flag[p])
            {
                c++;
            }
        }
        if(c == cnt || c + 1 == cnt)
        {
            cout << "City "<< attick<<" is lost."<< endl;
        }
        else
        {
             cout <<"Red Alert: City "<< attick<<" is lost!" << endl;
        }
        cnt = c;
        if(i == n -1)
        {
            cout << "Game Over." << endl;
        }
    }
    return 0;
}







 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值