#include
#include
#include
#define N 100005
using namespace std;
struct hh{int x,y;}bri[N];
int tot,point[N],nxt[N*2],v[N*2],nn,dfn[N],low[N],cnt,num;
bool vis[N],iscut[N];
void addline(int x,int y)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void tarjan(int now,int fa)
{
dfn[now]=low[now]=++nn;
int size=0;
for (int i=point[now];i;i=nxt[i])
if (!dfn[v[i]])
{
tarjan(v[i],now);
size++;
low[now]=min(low[now],low[v[i]]);
if (low[v[i]]>=dfn[now]) iscut[now]=1;
}
else low[now]=min(low[now],dfn[v[i]]);
if (!fa && size==1) iscut[now]=0;
}
int main()
{
int n,m,i;
scanf("%d%d",&n,&m);
for (i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
addline(x,y);
}
for (i=1;i<=n;i++)
if (!vis[i]) tarjan(i,0);
for (i=1;i<=n;i++)
if (iscut[i]) cnt++;
printf("%d\n",cnt);
for (i=1;i<=n;i++)
if (iscut[i]) printf("%d ",i);
}
其实也是先缩点然后看看剩下的边连接的点,这些边一定是桥,对于一个子图里所有的桥来说,ta们组成的是一棵树
#include
#include
#define N 10005
using namespace std;
int tot,nxt[N*2],point[N],v[N*2],dfn[N],nn,low[N],qq,stack[N],num,cnt;
bool vis[N];int x[N],y[N],belong[N],du[N];
void addline(int x,int y)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void tarjan(int x,int fa)
{
dfn[x]=low[x]=++nn;stack[++num]=x;vis[x]=1;
bool cf=0;
for (int i=point[x];i;i=nxt[i])
{
if (v[i]==fa && !cf){cf=1;continue;}
if (!dfn[v[i]])
{
tarjan(v[i],x);
low[x]=min(low[x],low[v[i]]);
}
else if (vis[v[i]]) low[x]=min(low[x],dfn[v[i]]);
}
if (low[x]==dfn[x])
{
cnt++;int now=0;
while (now!=x)
{
now=stack[num--];
vis[now]=0;
belong[now]=cnt;
}
}
}
int main()
{
int n,m,i;
scanf("%d%d",&n,&m);
for (i=1;i<=m;i++)
{
scanf("%d%d",&x[i],&y[i]);
addline(x[i],y[i]);
}
for (i=1;i<=n;i++)
if (!dfn[i]) tarjan(i,0);
for (i=1;i<=m;i++)
if (belong[x[i]]!=belong[y[i]])
du[belong[x[i]]]++,du[belong[y[i]]]++;
for (i=1;i<=n;i++)
if (du[i]==1) qq++;
printf("%d",(qq+1)/2);
}
优秀的学姐(为什么在前几个搜不到啊)
无向图的割点和桥:
割点:一个结点称为割点(或者割顶)当且仅当去掉该节点极其相关的边之后的子图不连通。
桥:一条边称为桥(或者割边)当且仅当去掉该边之后的子图不连通。
1)当前节点为树根的时候,要有多于一棵子树【特殊处理是因为普通处理翻不到更上面的点,这样如果只有一棵子树的话,也不能成为割点】
2)当前节点u不是树根的时候,条件是“low[v]>=dfn[u]”,也就是在u之后遍历的点,能够向上翻,最多到u。如果能翻到u的上方,那就有环了,去掉u之后,图仍然连通,u不能成为割点。
若是一条无向边(u,v)是桥
当且仅当无向边(u,v)是树枝边的时候,需要满足dfn(u) < low(v),也就是v向上翻不到u及其以上的点,当然不能通过ta从父亲来的那条边啦。
双连通分量有点双连通分量和边双连通分量两种。若一个无向图中的去掉任意一个节点(一条边)都不会改变此图的连通性,即不存在割点(桥),则称作点(边)双连通图。