题意
https://www.patest.cn/contests/pat-a-practise/1013
解题思路
刚开始的思路是,通过判断去除顶点的度和它所连接顶点是不是只依赖于它,来做统计。但是举了几个复杂例子后抛弃了用顶点的度做简单运算的想法,而是判断去除顶点后剩余的连通分量有多少个。
既然是连通分量,那先考虑的就是并查集了。
具体实现上,对于每个查询的顶点stop,为这张图构造去除它之后的所有连通分量,最后用顶点1(如果stop就是1,那就用2去尝试)去尝试连接所有顶点,来统计多少顶点无法到达(除去stop),即最后的答案。
AC代码
#include <iostream>
using namespace std;
const int maxn = 1005;
typedef struct node
{
int from, to;
}edge;
int n,m,k;
edge e[maxn*maxn]; //记录读入的所有边
int pre[maxn]; //并查集数据结构
void init()
{
for (int i = 1; i<=n; ++i) //初始化
pre[i] = i;
}
int find_root(int x)
{
if (pre[x] == x) //找到根节点
return x;
return (pre[x]=find_root(pre[x])); //递归同时路径压缩
}
int connect_left(int stop)
{
//并查集初始化
init();
//重构各个连通分量
int fx, fy;
for (int i = 0; i<m; ++i)
{
if (e[i].from == stop || e[i].to == stop) //不考虑stop点的连通
continue;
//尝试连接from和to的连通分量
fx = find_root(e[i].from);
fy = find_root(e[i].to);
//不在同一连通分量
if (fx != fy)
pre[fy] = fx;
}
int ans = 0;
//统计顶点1出发无法到达的连通分量数
int pivot = 1;
if (stop == 1) pivot = 2; //注意,stop可能为1
for (int i = pivot; i <= n; ++i)
{
if (i == stop) continue; //不考虑stop点
fx = find_root(pivot);
fy = find_root(i);
if (fx != fy)
{
ans++; //累加并用公路连起来
pre[fy] = fx;
}
}
return ans;
}
int main()
{
int stop, ans;
cin >> n >> m >> k;
for (int i = 0; i<m; ++i)
cin >> e[i].from >> e[i].to;
for (int i = 0; i<k; ++i)
{
cin >> stop;
ans = connect_left(stop); //去掉stop后所需新公路数
cout << ans << endl;
}
return 0;
}
一次AC,开心^-^