目录
1,题目描述
Sample Input:
3 2 3
1 2
1 3
1 2 3
Sample Output:
1
0
0
题目大意
举个例子吧(题目给出的):
假设有3个城市c1,c2,c3,两座桥b1,b2。若b1连接c1和c2,b2连接c1和c3,此时城市c1被占领,那么与c1有关的道路全部被封锁,要使其他两个城市保持联通,需要在c2与c3间建立桥梁。
输入
第一行:N:the total number of cities,M:the number of remaining highways(剩余的路的数量),K:the number of cities to be checked(我们关心的城市的数量)
中间M行:表示路连接的两个城市的编号
最后一行:表示我们关心哪K个城市;
输出
对每个城市来说,若这个城市被占领,则保持其他城市畅通,需要修多少条路;
注意
- 城市编号:1-N(N<1000);
- 关心的城市即假设被占领的城市,在DFS算法之前就已经被标记为 已访问;
- 最后一个测试点总是超时:上网查看了下其他大神的解法@Joyceyang_999【甲级PAT 1013 Battle Over Cities(用cin始终最后一个测试运行超时来看)】,以下为摘抄内容。
- 发现这里一定要用scanf输入而不是用cin输入。对于大量输入的操作,cin因为有同步机制所以会超时。这里有两种办法:
- 一、取消cin与stdin同步,在代码间添加ios::sync_with_stdio(false);即可
- 二、改用scanf输入
2,思路
简单的说就是求图中的联通分量的个数;
而且对每个关心的城市,都要计算一次;
连通分量
定义
无向图G的极大连通子图称为G的连通分量( Connected Component)。任何连通图的连通分量只有一个,即是其自身,非连通的无向图有多个连通分量。
求法
求连通分量可用DFS或是BFS(DFS简单些,故用的更加普遍),使用DFS可以从该节点开始形成一个树,所有与树上的节点相邻的点都会被访问到,未访问到的节点会在下一次或N次中,被访问到。
核心思想
每使用一次DFS后,图中的部分或全部节点就会被标记为已访问,只要图中还有节点未被访问,就一直使用DFS。
3,代码
#include<iostream>
using namespace std;
bool visited[1000];
bool graph[1000][1000];
int n, m, k;
void dfs(int start){
visited[start] = true;
for(int i = 1; i <= n; i++){ //i<=n
if(visited[i] == false && graph[start][i] == true){
dfs(i);
}
}
}
int main(){
//#ifdef ONLINE_JUDGE
//#else
// freopen("1.txt", "r", stdin);
//#endif
scanf("%d%d%d", &n, &m, &k);
for(int i = 0; i < m; i++){
int a, b;
scanf("%d%d", &a, &b);
graph[a][b] = graph[b][a] = true;
}
for(int i = 0; i < k; i++){
int city, num = 0;
scanf("%d", &city);
fill(visited, visited+n+1, false);
visited[city] = true;
for(int j = 1; j <= n; j++){//城市编号从1开始 且i<=n
if(visited[j] == false){
dfs(j);
num += 1;
}
}
printf("%d\n", num-1);
}
return 0;
}