浏览器标题切换
浏览器标题切换end

PTA1013 - Battle Over Cities - 求连通块模板题

题意

第一行给出n、m、k,表示有n个城市,给出m条路,k个被敌人占领的点。

接下去给出m行,每行有两个数x、y,表示x和y之间存在一条路(双向路)。

最后给出k个被敌人占领的点(设每个点为id),如果点id被占领,那么和点id相连接的所有路都无法走。

问如果我们想要剩下的所有城市可以相互访问到,需要再修几条路。

思路

第一种思路:在k个城市遍历的时候,我们求出除了id点之外,剩下的城市中有多少连通块,每次询问把剩下所有城市连接起来需要修建道路的答案数量就是:连通块 - 1。代码见下方。

第二种思路:并查集,见:https://zhanglong.blog.csdn.net/article/details/113777370

第三种思路:拓扑排序,自行查找。

注意

  1. 牛客上交的话要特判一下n==1的情况,PTA不用。

  2. 因为DFS所以要标记,但是因为本题间接求联通块所以不用回溯标记,这个要记住。

联通块AC代码

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<vector>
#include<stack>
#include<queue>

using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f

const int N=1010;
int n,m,k,e[N][N],id;
bool book[N];

void dfs(int x)
{
    for(int i=1;i<=n;i++)
    {
        if(i!=id&&e[x][i]&&!book[i]) // if(i!=x&&e[x][i]&&!book[i])
            book[i]=1,dfs(i);  // book[i]=0; 求连通块的话,不用递归回溯
    }
}

int main()
{
    cin>>n>>m>>k;
    if(n==1)
    {
        cout<<0<<endl;
        return 0;
    }
    for(int i=0;i<m;i++)
    {
        int x,y;
        cin>>x>>y;
        e[x][y]=e[y][x]=1;
    }
    for(int i=0;i<k;i++)
    {
        int ans=0;
        cin>>id;  // 排出x点和与x相连的所有边,求剩下所有点的连通块
        memset(book,0,sizeof(book));
        for(int j=1;j<=n;j++)
        {
            if(id!=j&&!book[j])
                book[j]=1,dfs(j),ans++;
        }
        cout<<ans-1<<endl;
    }
    return 0;
}
posted @ 2021-03-06 13:56  抓水母的派大星  阅读(58)  评论(0编辑  收藏  举报