https://pintia.cn/problem-sets/994805342720868352/problems/994805500414115840
1013 Battle Over Cities (25)(25 分)
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 (<1000), 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
题意理解
题意是,给你1~N个城市,以及这些城市之间的高速公路,问,如果某个城市被敌军占领,需要修复多少条告诉公路,才能保证余下公路的连通性。
这道题的本质,是一个图中,如果去掉某一个点,那么这张图需要添加多少条边来保持连通性。我们需要利用两个图的性质来完成连通性的检测。
思路及关键点
给定一个图,为使得整个图连通,最少需要增加的边数;
等价于:图的连通块的个数-1
以下是用邻接矩阵实现的,记住:cin、cout比printf慢,因此最后一个测试点会超时,过不去。
加入以下这一行代码:
ios_base::sync_with_stdio(false);
cin.tie(0)
AC code(BFS+邻接矩阵)满分
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int nmax=1005;
int G[nmax][nmax];
int vis[nmax];//若顶点i加入过队列,则vis[i]=1,否则vis[i]=0;
int n,m,q;
void BFS(int x){//遍历点x所在的连通块
queue<int>q;
q.push(x);
//vis[x]=1; //for里和for外写一个就可以
while(!q.empty()){
int u=q.front();
q.pop();
for(int v=1;v<=n;v++){//图中点下标1~N
//若u的邻接节点v未曾加入过队列,且点u到点v可及
if((vis[v]==0)&&(G[u][v]==1)){
vis[v]=1;//for里和for外写一个就可以
q.push(v);
}
}
}
}
int main(int argc, char** argv) {
ios::sync_with_stdio(false);
cin>>n>>m>>q;//点数,边数,查询
for(int i=0;i<m;i++){
int u,v;
cin>>u>>v;
G[u][v]=1;
G[v][u]=1;
}
int curP;
//int blk=0;
for(int i=0;i<q;i++){
memset(vis,0,sizeof(vis));
int blk=0;
cin>>curP;
vis[curP]=1;
for(int j=1;j<=n;j++){
if(vis[j]==0){
vis[j]=1;//
BFS(j);
blk++;
}
}
cout<<blk-1<<endl;
}
return 0;
}
AC Code(BFS+邻接表) 满分
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int nmax=1005;
vector<int> G[nmax];
int vis[nmax];//若顶点i加入过队列,则vis[i]=1,否则vis[i]=0;
int n,m,q;
void BFS(int x){//遍历点x所在的连通块
queue<int>q;
q.push(x);
//vis[x]=1; //for里和for外写一个就可以
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<G[u].size();i++){//枚举能从u出发到达的所有顶点
int v=G[u][i];
if(vis[v]==0){
vis[v]=1;//for里和for外写一个就可以
q.push(v);
}
}
}
}
int main(int argc, char** argv) {
ios::sync_with_stdio(false);
cin>>n>>m>>q;//点数,边数,查询
for(int i=0;i<m;i++){
int u,v;
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
int curP;
//int blk=0;
for(int i=0;i<q;i++){
memset(vis,0,sizeof(vis));
int blk=0;
cin>>curP;
vis[curP]=1;
for(int j=1;j<=n;j++){
if(vis[j]==0){
vis[j]=1;//如果BFS里不写,这里就得写
BFS(j);
blk++;
}
}
cout<<blk-1<<endl;
}
return 0;
}