PAT甲题 1013 Battle Over Cities

PAT甲题 1013 Battle Over Cities


刚读完这题有点懵,准确的说是数据结构没好好学的我有点心虚,不知如何下手,翻出教材把求割点的算法仔细读了一下,没啥帮助,后来顿悟,其实这题只需要无脑dfs就可以了。

题意回顾:

在战争中,使自己的所有领地(拥有的城市)保持连通是很重要的,所谓保持连通即城市之间有公路连接,画成图模型即此图为连通图。但是战争中自己的某个城市很有可能被敌方占领,这就可能使我们本来连通的图变的不连通,于是我们就得修建公路使我们剩下的城市之间再次组成连通图。
输入规格:
1.第一行包含三个正整数,N,M,K,其中N<1000,它们分别代表你拥有的城市数,现有公路数,和你需要检查的公路数。我们以1到N对城市进行标号。接下来有M行输入,每行有两个城市号,意味着这两个城市之间有一条公路连通。最后一行有K个整数,每一个代表我们需要检查的城市号。
输出规格:
依次输出需要检查的城市如果沦陷我们需要建的公路数,每个输出占一行。

个人思路:

1.用邻接矩阵或者邻接表来存储城市间的道路信息,我偷懒用了邻接矩阵,打算超时再改邻接表,实际上道路并不会很多,所以这种稀疏矩阵用链表来写效率会高得多;
2.用dfs来进行遍历,每次挑选未遍历过的非此次沦陷的城市,直到除了沦陷城市所有城市都被遍历过。设遍历次数为n,撇开沦陷的城市不看,此时有n个连通图(也有可能有的是孤立结点),则我们需建n-1条路;
3.用map存储某个结点是否被遍历过,关键字为城市号,值为是否被遍历过(bool);
4.个人觉得此题没什么坑点,掌握好算法,别超时就好。

代码:

#include<iostream>
#include<map>
using namespace std;
int N, M, K, a, b, hs = 0;  //hs存储已经遍历过的结点数
int adj[1000][1000] = {};   //邻接矩阵
map<int, bool> mp;
void dfs(int v, int w)  //递归深搜
{
 mp[v] = true;
 hs++;
 for (int i = 1; i <= N; i++)
 	 if (adj[i][v] && !mp[i] && i != w)
  		 dfs(i, w);
}
int Number(int w)
{
 int count = -1;
 for (int i = 1; hs != N - 1; i++)
	  if (!mp[i] && i != w) //不能以沦陷的城市为起点进行深搜
 	 {
  		 dfs(i, w);
  		 count++;
 	 } 
 hs = 0;  
 mp.clear();  //记得把hs和mp都还原
 return count;
}
int main()
{
 cin >> N >> M >> K;
 for (int i = 0; i < M; i++)
 {
 	 cin >> a >> b;
 	 adj[a][b] = adj[b][a] = 1;
 }
 for (int i = 0; i < K; i++)
 {
	  cin >> a;
	  cout << Number(a) << endl;
 }
 return 0;
}

这边的算法效率还是可以继续优化的,思路之一就是使用邻接表,我多提交了几次发现有时候最后一个测试点是会超时的,没有超时也在350ms+,所以还是在扣分边缘徘徊。。

原文地址:https://www.cnblogs.com/yuhan-blog/p/12309118.html