PAT (Advanced Level) Practice 笔记
记录做PAT (Advanced Level) Practice时遇到的坑和总结一、描述
删除图的某个节点,求联通分量的个数
二、题目链接
1013 Battle Over Cities (25 分)
三、代码
1.AC
#include <iostream>
using namespace std;
const int MaxSize=1005;
int Graph[10][MaxSize][MaxSize]={{{0}}};
int id_Graph=0;
int res=0; //输出结果,子图数量
int nodes=0; //已经遍历的节点个数
bool visited[MaxSize]={false};
void Print()
{
for (int i=0;i<3;i++)
{
for (int j=0;j<3;j++)
cout << Graph[id_Graph][i][j] << ' ';
cout << endl;
}
}
void dfs(int v,int n)
{
//cout << "test" << endl;
for (int w=0;w<n;w++)
{
if (Graph[id_Graph][v][w]==1 && !visited[w])
{
visited[w]=true;
nodes++;
//cout << "now nodes=" << nodes << endl;
dfs(w,n);
}
}
}
int main()
{
int n,m,k,tmp1,tmp2,v1,v2;
scanf("%d %d %d",&n,&m,&k);
//cout << n << ' ' << m << ' ' << k << endl;
for (int i=0;i<m;i++)
{
scanf("%d %d",&tmp1,&tmp2);
v1=tmp1-1;
v2=tmp2-1;
//数组中的0是节点1
//cout << tmp1 << ' ' << tmp2 << endl;
for (int j=0;j<k;j++) //存储k张图
{
Graph[j][v1][v2]=1;
Graph[j][v2][v1]=1;
}
}
//Print();
for (;id_Graph<k;id_Graph++)
{
//cout << "id_Graph=" << id_Graph << endl;
scanf("%d",&tmp1);
v1=tmp1-1;
//cout << "v1=" << v1 << endl;
//切断v1与其他点的联系
for (int j=0;j<n;j++)
{
Graph[id_Graph][v1][j]=0;
Graph[id_Graph][j][v1]=0;
}
//Print();
//遍历所有节点,能联通的排除,计算不连通的子图数量
//for (int i=0;i<n;i++) cout << visited[i] << endl;
while (nodes<n) //还有点未被访问
{
int vertex=0;
//cout << nodes << endl;
for (;vertex<n && visited[vertex];vertex++); //找到未被访问的点
//cout << "vertex=" << vertex << endl;
visited[vertex]=true;
nodes++;
//遍历和这个点联通的点
dfs(vertex,n);
res++; //遍历退出,与这个点联通的子图已经遍历结束
}
//有res个子图,其中有一个是被割断的孤立点,不需要建立连接,剩下每个子图之间都需要一个连接
int output=res-2;
cout << output << endl;
res=nodes=0;
for (int j=0;j<n;j++) visited[j]=false;
}
}
2.学习
代码来自 1013. Battle Over Cities (25)-PAT甲级真题(图的遍历,统计强连通分量的个数,dfs)
#include <cstdio>
#include <algorithm>
using namespace std;
int v[1010][1010];
bool visit[1010];
int n;
void dfs(int node) {
visit[node] = true;
for(int i = 1; i <= n; i++) {
if(visit[i] == false && v[node][i] == 1)
dfs(i);
}
}
int main() {
int m, k, a, b;
scanf("%d%d%d", &n, &m, &k);
for(int i = 0; i < m; i++) {
scanf("%d%d", &a, &b);
v[a][b] = v[b][a] = 1;
}
for(int i = 0; i < k; i++) {
fill(visit, visit + 1010, false);
scanf("%d", &a);
int cnt = 0;
visit[a] = true;
for(int j = 1; j <= n; j++) {
if(visit[j] == false) {
dfs(j);
cnt++;
}
}
printf("%d\n", cnt - 1);
}
return 0;
}
四、总结
- 删除图节点可以用visited[i]=true来表示,不需要把连接删除
- 保证图的每个节点都被遍历也可以通过完全遍历和visited[i]==false来确定