什么时候用到图的割点呢?(当删除一个顶点后,图的连通量个数发生变化。)例如两国打仗,让你找到一个攻击点攻击后致使敌方的原连通的地方不再连同)如同所示:
/*
6 7
1 4
1 3
4 2
3 2
2 5
2 6
5 6
2
*/
#include<stdio.h>
#include<string.h>
#define min(a,b) a<b?a:b
using namespace std;
int n,m,root;
int num[9],low[9],flag[9],index,t;
int head[9];
struct edge
{
int u,v;
int w;
int next;
}e[9*9];
void dfs(int cur,int f)
{
int c=0,i,j;
index++;
num[cur]=low[cur]=index;
int k=head[cur];
while(k!=-1)//找以cur出度的边
{
i=e[k].v;
if(num[i]==0)//节点i没有遍历过
{
c++;//记录节点i的孩子数目
dfs(i,cur);
low[cur]=min(low[cur],low[i]);
if(cur!=root && low[i] >= num[cur])//找割点_分情况根节点是不是割点,如果割点不是根节点判断条件是low[v]>=num[u];
{
flag[cur]=1;
}
if(cur==root && c==2)//割点是根节点的判断条件是如果孩子数目大于等于2个就是割点。
{
flag[cur]=1;
}
}
else if(i!=f)//i节点遍历过并且成环
{
low[cur]=min(low[cur],num[i]);
}
k=e[k].next;
}
}
int main()
{
int i,j,x,y,t=0;
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));//数组实现链接表
memset(num,0,sizeof(num));//常见的dfn时间戳
memset(low,0,sizeof(low));//记录能够回到其最早的祖先节点的时间戳
memset(flag,0,sizeof(flag));
for(i=1;i<=n;i++)
{
e[i].w=0;
}
for(i=1;i<=m+m;i+=2)
{
scanf("%d%d",&e[i].u,&e[i].v);
e[i].next=head[e[i].u];
head[e[i].u]=i;
e[i+1].u=e[i].v;//双向边
e[i+1].v=e[i].u;
e[i+1].next=head[e[i+1].u];
head[e[i+1].u]=i+1;
}
root=1;
dfs(1,root);
for(i=1;i<=n;i++)
{
if(flag[i]==1)//flag标记割点
printf("%d ",i);
}
return 0;
}