1013 Battle Over Cities (25)(25 分)



1 题目


  It is vitally important to have all the cities connected by highways in a war. If a city is occupied by the enemy, all the highways from/toward that city are closed. We must know immediately if we need to repair any other highways to keep the rest of the cities connected. Given the map of cities which have all the remaining highways marked, you are supposed to tell the number of highways need to be repaired, quickly.
  For example, if we have 3 cities and 2 highways connecting city~1~-city~2~ and city~1~-city~3~. Then if city~1~ is occupied by the enemy, we must have 1 highway repaired, that is the highway city~2~-city~3~.

Input

  Each input file contains one test case. Each case starts with a line containing 3 numbers N (&lt1000), M and K, which are the total number of cities, the number of remaining highways, and the number of cities to be checked, respectively. Then M lines follow, each describes a highway by 2 integers, which are the numbers of the cities the highway connects. The cities are numbered from 1 to N. Finally there is a line containing K numbers, which represent the cities we concern.

Output

For each of the K cities, output in a line the number of highways need to be repaired if that city is lost.

Sample Input :

3 2 3
1 2
1 3
1 2 3

Sample Output

1
0
0

题目链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805500414115840

2 解题思路

  题意是,给你1~N个城市,以及这些城市之间的高速公路,问,如果某个城市被敌军占领,需要修复多少条告诉公路,才能保证余下公路的连通性。
  这道题的本质,是一个图中,如果去掉某一个点,那么这张图需要添加多少条边来保持连通性。我们需要利用两个图的性质来完成连通性的检测。

  • 深度优先搜索访问整张图的顶点,计算连通分量的个数,连通分量可以视为一个点
  • 一个N个顶点的连通图,至少需要N-1条边

  基于上述知识背景,这道题就比较简单了。通过一个二维数组来存储整张图,然后另外通过一个一维数组来记录访问过程,一个计数变量来计算连通分量的个数,最后得出需要额外补充的边。

  一点小曲折:之前一直听说printf和scanf效率要远高于std::cout和std::cin,一直不以为意,因为cout和cin要方便很多,本题的最后一个测试点,如果使用cout和cin,会运行超时
这里写图片描述  一开始不知道为什么会超时,想来想去找不到原因,好在这道题的代码量不是很大,逐一排查,最后发现是输入输出流的锅,恶补了一波cout和cin的知识,才知道cout和cin的性能差这么多。
  cout和cin的设计,可能比我们想象的复杂的多,从实际测试的结果,速度比printf和scanf慢一个数量级以上。影响cout和cin的性能的有两个方面:同步性缓冲区,同步性可以通过ios_base::sync_with_stdio(false)禁用;操作系统会对缓冲区进行管理和优化,但十分有限,使用了endl之后,会对缓冲区执行清空操作,这个过程会先执行’\n’,再执行flush操作,非常漫长,所以尽量使用‘\n’而不是endl执行换行。然后,还有一个cout和cin的绑定效果,两者同时使用的话,cin与cout交替操作,会有一个flush过程,所以还是会很漫长,可以通过cin.tie(0)禁用绑定。
  但是需要注意的是,禁用同步之后,printf和scanf就不能用了,所以绕了一圈,还是用printf和scanf吧……

3 AC代码


/*
**@Brief: No.1012 of PAT advanced level.
**@Author: Jason.Lee
**@Date: 2018-7-11 
*/ 

#include<iostream>
#include<algorithm>
#define NODE_NUM 1001
using namespace std;

int v[NODE_NUM][NODE_NUM];
bool visited[NODE_NUM];
int N;
void dfs(int node){
    visited[node] = true;
    for(int i=1;i<=N;i++){
        if(visited[i]==false && v[node][i]==1)
            dfs(i);
    }
}

int main(){
    int M,K;
    ios_base::sync_with_stdio(false);
    while(cin>>N>>M>>K){
        cin.tie(0);
        fill(v[0],v[0]+NODE_NUM*NODE_NUM,0);
        for(int i=0;i<M;i++){
            int city1,city2;
            //scanf("%d%d",&city1,&city2);
            cin>>city1>>city2; 
            v[city1][city2] = v[city2][city1] = 1;
        } 

        for(int i=0;i<K;i++){
            int count = 0;
            fill(visited,visited+NODE_NUM,false);
            int city;
            cin>>city;
            visited[city] = true;
            for(int j = 1;j<=N;j++){
                if(visited[j]==false){
                    dfs(j);
                    count++;
                }
            }
            cout<<count-1<<endl;
        }
    } 
    return 0;
} 
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页