刚读完这题有点懵,准确的说是数据结构没好好学的我有点心虚,不知如何下手,翻出教材把求割点的算法仔细读了一下,没啥帮助,后来顿悟,其实这题只需要无脑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+,所以还是在扣分边缘徘徊。。