PAT甲级1013 (图,DFS举例详解)

题目

It is vitally important to have all the cities connected by highways in a war. If a city is occupied by the enemy, all the highways from/toward that city are closed. We must know immediately if we need to repair any other highways to keep the rest of the cities connected. Given the map of cities which have all the remaining highways marked, you are supposed to tell the number of highways need to be repaired, quickly.

For example, if we have 3 cities and 2 highways connecting city1-city2 and city1-city3. Then if city1 is occupied by the enemy, we must have 1 highway repaired, that is the highway city2-city3.

Input

Each input file contains one test case. Each case starts with a line containing 3 numbers N (<1000), M and K, which are the total number of cities, the number of remaining highways, and the number of cities to be checked, respectively. Then M lines follow, each describes a highway by 2 integers, which are the numbers of the cities the highway connects. The cities are numbered from 1 to N. Finally there is a line containing K numbers, which represent the cities we concern.

Output

For each of the K cities, output in a line the number of highways need to be repaired if that city is lost.

Sample Input
3 2 3
1 2
1 3
1 2 3
Sample Output
1
0
0


题解

//保证剩余城市的连接
#include<iostream>
#include<algorithm>
using namespace std;
bool vis[1001];
int G[1001][1001];
int n;
void dfs(int node){
  vis[node]=true;
  for(int i=1;i<=n;i++){
     if(vis[i]==false&&G[node][i]==1){
     dfs(i);
  }
}
 
}
int main(){
  int m,k;
  scanf("%d%d%d", &n, &m, &k);
  int u,v;
  for(int i=0;i<m;i++){
    scanf("%d%d", &u, &v);
    G[u][v]=G[v][u]=1;
  }
  for(int i=0;i<k;i++){//输入被去除的城市
    fill(vis,vis+1001,false);
    int a;
    scanf("%d",&a);
    vis[a]=true;
    //去除选中点与其他点的连接
    int cnt=0;
    for(int j=1;j<=n;j++){//找去除点后的入口1⃣️
      if(vis[j]==false){
        dfs(j);//未访问的就是入口,找到一个入口后进入迭代
        cnt++;
      }
    }
    //dfs内,判断入口和其余的点是否联通,尽量走完所有节点
    //若未访问完全部节点退出迭代,退回仍有未访问分支的岔路口,即进入1⃣️换一个入口
     printf("%d\n",cnt-1);
  }
  return 0;
}

举个例子:

去除的点是1,则vis[1]=true,找入口(未访问的点),找到2,vis[2]=false,进入2为入口的DFS(2)。

进入DFS使得vis[2]=true,剩余没访问的点只有3,但G[2][3]没有连接,退出此次迭代。cnt++,为1。

DFS尽力了但没有走完所有节点。此时还有3没走到。以3为新的入口,进入DFS(3)。使得vis[3]=true。现在点全访问到了,此次迭代结束。cnt++,为2。

迭代两次走完了,去除点a后的所有点,说明有两块未连通区域,至少需要一条路使得他们连接。

扫描二维码关注公众号,回复: 3304943 查看本文章

DFS这块之前理解得不是太好。
思路是只要有去除的点a外的点没有访问,就找一个入口,进入dfs迭代,找从这个入口能访问到的所有点。迭代一次全走完说明不用加路,迭代n次说明有n块未连通区域,需要n-1条路。

猜你喜欢

转载自blog.csdn.net/qq_24572475/article/details/82818089