[啊哈算法]重要城市(图的割点)

一场大战即将开始...

我们已经掌握了敌人的城市地图,为了在战争中先发制人,决定向敌人的某个城市上空投放炸弹,来切断敌人城市之间的通讯和补给,城市地图如下:

我们可以炸毁2号城市,这样剩下的城市之间就不能两两相护到达了。

Input

第一行有两个整数n,m。n表示有n个顶点,m表示有m条边,

接下来m行,每行形如“a b”表示顶点a和顶点b之间有边。

Output

输出要炸毁的城市。

Sample Input

6 7
1 4
1 3
4 2
3 2
2 5
2 6
5 6

Sample Output

2


 1 #include<iostream>
 2 using namespace std;
 3 int n,m;
 4 int flag[104];//用来标记那些点是割点 
 5 int e[104][104];//用来存储图 
 6 int low[104],num[103];//low数组来存储该节点在不经过父节点时,能够回到的最小时间戳
 7                         //num数组来存储该节点的时间戳 
 8 int index;//用来记录时间戳 
 9 int root;//根节点 
10 void dfs(int cur,int father){
11     int child=0;//进入一个dfs,一开始时该节点的孩子是0 
12     index++;//时间戳增加 
13     num[cur]=index;//记录时间戳 
14     low[cur]=index;//这时,该节点能达到的最小时间戳就是自己 
15     for(int i=1;i<=n;i++){//遍历每个点, 
16         if(e[cur][i]==1){//如果有路 
17             if(num[i]==0){//如果i节点没有被搜索过 
18                 child++;//cur节点的孩子增加一个 
19                 dfs(i,cur);// 从i节点继续搜索 
20                 low[cur]=min(low[cur],low[i]);//搜索回来后,更新cur节点的low数组 
21                 if(cur!=root&&low[i]>=num[cur])//如果cur节点不是根节点
22                         //并且i节点能达到的最小时间戳>=cur节点的时间戳 
23                     flag[cur]=1;//cur为割点 
24                 if(cur==root&&child==2)//如果cur是根节点,并且cur有两个孩子 
25                     flag[cur]=1;    //那么cur一定为割点 
26             }
27             else if(i!=father)//如果i节点不是cur的父节点 
28                 low[cur]=min(low[cur],num[i]);//要这样更新cur节点的low数组 
29         }
30     }
31 }
32 int main(){
33     scanf("%d%d",&n,&m);
34     for(int i=1;i<=n;i++){
35         for(int j=1;j<=n;j++){
36             e[i][j]=0;
37         }
38     }
39     int a,b;
40     for(int i=1;i<=m;i++){
41         scanf("%d%d",&a,&b);
42         e[a][b]=1;
43         e[b][a]=1;
44     }
45     root=1;
46     dfs(1,root);
47     for(int i=1;i<=n;i++){
48         if(flag[i]==1){
49             printf("%d",i);
50         }
51     }
52     return 0;
53 } 






原文地址:https://www.cnblogs.com/fate-/p/12254625.html