• PTA1013


    题意

    第一行给出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;
    }
    
  • 相关阅读:
    B3
    B2
    b1
    个人作业——软件工程实践总结作业
    Beta 答辩总结
    Beta 冲刺 (7/7)
    Beta 冲刺 (6/7)
    Beta 冲刺 (5/7)
    Beta 冲刺 (4/7)
    Beta 冲刺 (3/7)
  • 原文地址:https://www.cnblogs.com/OFSHK/p/14490438.html
Copyright © 2020-2023  润新知