【PAT甲级、C++、图】1013 Battle Over Cities (25分)

今天买的晴神宝典终于到了,刚好找到这题有题解,代码写的是真的不错,简单易懂,就是写代码的风格跟我平常的风格不太一样,还是要适应一下,不过至少不用在网上找各种风格迥异的题解了,加油~~~~

# include <iostream>
# include <vector>
# include <cstring>

using namespace std;

/*
输入:
    N(城市总数) M(路的数量) K(要检查是否到其他城市有通路的城市数量)
    M条路(u->v)
    K个待检查的城市的序号i
    
输出:
    第i个城市如果沦陷了,那么剩下的城市为了形成通路应修的路的个数

创建邻接矩阵
使用DFS
*/

const int MAXSIZE = 1111;
vector<bool> visited(MAXSIZE);
vector<int> G[MAXSIZE];


// 在DFS中:对于遇到要删除的顶点,并不用真的删除,跳过即可
// 在主函数中:对于遇到要删除的顶点,不进行以其开始的连通分量的遍历(可以对其所在的连通分量换个起点,反正就不要已它为起点)
void DFS(int u, int occupied)
{
    // 对于遇到要删除的顶点,并不用真的删除,跳过即可
    if(u == occupied)
        return;
    
    visited[u] = true;
    
//     for(size_t i=0;i<G[u].size();++i)
//     {
//         int v = G[u][i];
//         if(visited[v] == false)
//             DFS(v, occupied);
//     }
    
    for(size_t v=0;v<G[u].size();++v)
    {
        if(visited[G[u][v]] == false)
            DFS(G[u][v], occupied);
    }
}


int main()
{
    int N, M, K;
    cin >> N >> M >> K;
    
    // 创建邻接表,要习惯晴神的写法……
    for(int i=0;i<M;++i){
        int a, b;
        cin >> a >> b;
        G[a].push_back(b);  // a->b
        G[b].push_back(a);  // b->a
    }
    
    // 进行K次查询,每次都对图进行一次遍历
    for(int i=0;i<K;++i){
        int occupied;    // 欲被删除(占领)的顶点
        cin >> occupied;
        visited = vector<bool>(MAXSIZE, false); // 对于每一次查询都要遍历一次图,所以visited数组要重新设置
        
        int num_of_connected_component=0; // 用来记录连通分量的个数,
        for(int u=1;u<=N;u++) // 枚举所有顶点
            if(u != occupied && visited[u] == false){  // 跳过被删除和已被访问过的顶点
                DFS(u, occupied);                     // 一条路走到底,说明每完成一次DFS函数,就有一个连通分量存在
                num_of_connected_component++;         // 所以连通分量的个数++
            }
        cout << num_of_connected_component - 1 << endl;  // 想想,n个连通分量需要n-1条边来连接!!
    }
        
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值