题目
解决思路
如果删除某点后导致图不连通, 图中剩下N个连通块,这需要补 N - 1 条路
如果删除某点后图仍连通, 则无需补;
并查集思路,删除某点后,看还剩多少个集合
代码
遍历图,当遇到要删除的点,则停止往下遍历
邻接表
#include<stdio.h>
#include<vector>
#include<string.h>
using namespace std;
const int maxn = 1010;
vector<int> G[maxn];
bool vis[maxn]; // 城市从1-N
int n, m, k; // 城市数量, M条仍存在的公路,被检查的城市
int currentPoint;
void DFS(int v)
{
if(v == currentPoint)
return;
vis[v] = true;
for (int i = 0; i < G[v].size(); i++)
{
if(vis[G[v][i]] == false)
{
DFS(G[v][i]);
}
}
}
int main()
{
scanf("%d%d%d", &n, &m, &k);
int st, ed;
for (int i = 0; i < m; i++)
{
scanf("%d%d", &st, &ed);
G[st].push_back(ed);
G[ed].push_back(st);
}
for (int i = 0; i < k; i++)
{
int block = 0;
scanf("%d", ¤tPoint);
memset(vis, false, sizeof(vis));
for (int j = 1; j <= n; j++)
{ // 城市从1-N
if(j != currentPoint && vis[j] == false)
{
DFS(j);
block++;
}
}
printf("%d\n", block-1);
}
return 0;
}
邻接矩阵
#include<stdio.h>
#include<vector>
#include<string.h>
using namespace std;
const int maxn = 1010;
int G[maxn][maxn];
bool vis[maxn]; // 城市从1-N
int n, m, k; // 城市数量, M条仍存在的公路,被检查的城市
int currentPoint;
void DFS(int v)
{
if(v == currentPoint)
return;
vis[v] = true;
for (int i = 1; i <= n; i++)
{
if(vis[G[v][i]] == false)
{
DFS(G[v][i]);
}
}
}
int main()
{
scanf("%d%d%d", &n, &m, &k);
int st, ed;
for (int i = 0; i < m; i++)
{
scanf("%d%d", &st, &ed);
G[st][ed] = ed;
G[ed][st] = st;
}
for (int i = 0; i < k; i++)
{
int block = 0;
scanf("%d", ¤tPoint);
memset(vis, false, sizeof(vis));
for (int j = 1; j <= n; j++)
{ // 城市从1-N
if(j != currentPoint && vis[j] == false)
{
DFS(j);
block++;
}
}
printf("%d\n", block-1);
}
return 0;
}
并查集
#include<stdio.h>
#include<vector>
using namespace std;
const int maxn = 1010;
vector<int> G[maxn];
int father[maxn];
bool vis[maxn];
int findFather(int x)
{
int a = x;
while (x != father[x])
{
x = father[x];
}
while (a != father[a])
{
int z = a;
a = father[a];
father[z] = x;
}
return x;
}
void Union(int a, int b)
{
int faA = findFather(a);
int faB = findFather(b);
if( faA != faB)
{
father[faA] = faB;
}
}
void init()
{
for (int i = 0; i < maxn; i++)
{
father[i] = i;
vis[i] = false;
}
}
int n, m, k;
int main()
{
scanf("%d%d%d", &n, &m, &k);
int st, ed;
for (int i = 0; i < m; i++)
{
scanf("%d%d", &st, &ed);
G[st].push_back(ed);
G[ed].push_back(st);
}
int currentPoint;
for (int query = 0; query < k; query++)
{
scanf("%d", ¤tPoint);
init();
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < G[i].size(); j++)
{
int u = i, v = G[i][j];
if(u == currentPoint || v == currentPoint)
continue; // 相当于删除所有与current相连的边
Union(u, v);
}
}
int block = 0;
for (int i = 1; i <= n; i++)
{
if(i == currentPoint)
continue;
int fa_i = findFather(i);
if(vis[fa_i] == false)
{
block++;
vis[fa_i] = true;
}
}
printf("%d\n", block - 1);
}
}