前几天参加省赛了,无语凝咽。。。
又学了一年竟然还不如大一的时候,还是踏实点吧
割点和桥 简单的说就是去掉一个点或者一条边 原来的图变成了两个或者更多的图
vis[v]记录的是节点v当前的访问状态,1表示在栈中,0,表示未访问,2表示已经访问过;
dfn[v]记录的是节点v被访问时的时间;
low[v]记录的是点v可以到达的访问时间最早的祖先
在深搜的过程中,对于当前节点cur,记录dnf[cur],和与它相连的节点i,两种情况
1.i未被访问过,深搜i,回溯的时候更新low[cur]=min(low[cur],low[i])
2.i在栈中,那么更新 low[cur]=min(low[cur],dnf[i])
如果cur是根节点并且孩子超过一个,那么cur是割点
如果cur不是根节点并且low[i]>=dfn[cur],即cur的所有孩子最早的祖先都没有超过当前节点,那么cur是割点
如果low[i]>dfn[cur],那么(cur,i)是桥
举个例子,深搜时
d=1 l=1 d=2 l=2
1--------2--------5--------6
| | |
| | |
3--------4--------|
d=4 l=4 d=3 l=3
当深搜到节点3的时候,存在边(1,3),因为节点1在栈中,那么low[3]=1,回溯过程更新节点4,变成
d=1 l=1 d=2 l=2
1--------2--------5--------6
| | |
| | |
3--------4--------|
d=4 l=1 d=3 l=1
继续深搜5,6,回溯更新节点2
d=1 l=1 d=2 l=1 d=5 l=5 d=6 l=6
1--------2--------5--------6
| | |
| | |
3--------4--------|
d=4 l=1 d=3 l=1
又学了一年竟然还不如大一的时候,还是踏实点吧
割点和桥 简单的说就是去掉一个点或者一条边 原来的图变成了两个或者更多的图
vis[v]记录的是节点v当前的访问状态,1表示在栈中,0,表示未访问,2表示已经访问过;
dfn[v]记录的是节点v被访问时的时间;
low[v]记录的是点v可以到达的访问时间最早的祖先
在深搜的过程中,对于当前节点cur,记录dnf[cur],和与它相连的节点i,两种情况
1.i未被访问过,深搜i,回溯的时候更新low[cur]=min(low[cur],low[i])
2.i在栈中,那么更新 low[cur]=min(low[cur],dnf[i])
如果cur是根节点并且孩子超过一个,那么cur是割点
如果cur不是根节点并且low[i]>=dfn[cur],即cur的所有孩子最早的祖先都没有超过当前节点,那么cur是割点
如果low[i]>dfn[cur],那么(cur,i)是桥
举个例子,深搜时
d=1 l=1 d=2 l=2
1--------2--------5--------6
| | |
| | |
3--------4--------|
d=4 l=4 d=3 l=3
当深搜到节点3的时候,存在边(1,3),因为节点1在栈中,那么low[3]=1,回溯过程更新节点4,变成
d=1 l=1 d=2 l=2
1--------2--------5--------6
| | |
| | |
3--------4--------|
d=4 l=1 d=3 l=1
继续深搜5,6,回溯更新节点2
d=1 l=1 d=2 l=1 d=5 l=5 d=6 l=6
1--------2--------5--------6
| | |
| | |
3--------4--------|
d=4 l=1 d=3 l=1
因为节点1只有一个孩子(节点2,没有节点4),而对于节点5,low[6]>dfn[5],所以节点5为割点
# include <stdio.h>
# include <string.h>
# include <iostream>
using namespace std;
const int maxn=105;
int map[maxn][maxn];
int dfn[maxn],low[maxn],vis[maxn];
int res[maxn];
void cut(int cur,int father,int dep,int n)
{
vis[cur]=1;
dfn[cur]=low[cur]=dep;
int i;
int children=0;
for(i=1; i<=n; i++){
if(map[cur][i]){
if(vis[i]==1&&i!=father) low[cur]=min(low[cur],dfn[i]);
if(vis[i]==0)
{
cut(i,cur,dep+1,n);
children++;
low[cur]=min(low[i],low[cur]);
if(father==-1&&children>1 || father!=-1&&low[i]>=dfn[cur]) res[cur]=1;
}
}
}
vis[cur]=2;
}
int main()
{
int n,ans;
while(scanf("%d",&n),n)
{
memset(map,0,sizeof(map));
memset(vis,0,sizeof(vis));
memset(res,0,sizeof(res));
//memset(dfn,0,sizeof(dfn));
//memset(low,0,sizeof(low));
int a,b;
ans=0;
while(scanf("%d",&a),a){
while(scanf("%d",&b)!=EOF)
{
map[a][b]=1;
map[b][a]=1;
//printf("%d\n",b);
char c;
c=getchar();
if(c=='\n') break;
}
}
cut(1,-1,0,n);
for(int i=1; i<=n; i++) if(res[i]) ans++;
printf("%d\n",ans);
}
}