割点和桥的数量

题目描述
给定无向图G,请求出G 中的割点和桥的个数。

输入
第一行两个整数n,m,代表图的顶点数和边数。
接下来m 行,每行两个整数u, v,描述一条无向边。

输出
输出两个整数,先输出割点的数量和再输出桥的数量,用一个空格隔开。

样例输入
4 5
1 2
1 2
2 3
2 3
3 4
样例输出
2 1

提示
20% n<=50
50% n<=500
100% n<=50000, m<=200000

这题还真是赤裸裸哈。。。
考试的时候还推了一下,其实桥和割点的关键就在于
low[to[i]]>dfn[k]和low[to[i]]>=dfn[k]
还有dfs树中根节点是否为割点的特判

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,tot,x,y,ty,root,cutid,cutedge;
int dfn[50005],low[50005],cut[50005],instack[50005];
int head[50005],Next[400005],to[400005];
void tarjan(int k,int pre)
{
    dfn[k]=low[k]=++ty;
    instack[k]=1;
    int ok=0,son=0;
    for(int i=head[k];i!=-1;i=Next[i]) 
    {
        if(to[i]==pre&&ok==0) 
        {
            ok=1;
            continue;
        }
        if(dfn[to[i]]==0) 
        {
            son++;
            tarjan(to[i],k);
            if(low[to[i]]>dfn[k]) cutedge++; //桥 
            if(low[to[i]]>=dfn[k]) cut[k]=1; //是不是割点 
            low[k]=min(low[k],low[to[i]]);
        }
        else
        if(instack[to[i]]) low[k]=min(low[k],dfn[to[i]]);
    }
    if(k==root)  //根要特判 
    {
        if(son>1) cut[k]=1; else cut[k]=0;
    }
    instack[k]=0;
}
void add(int x,int y)
{
    tot++;
    Next[tot]=head[x];
    to[tot]=y;
    head[x]=tot;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) head[i]=-1;
    for(int i=1;i<=m;i++) 
    {
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    for(int i=1;i<=n;i++) 
    if(dfn[i]==0) 
    {
        root=i;
        tarjan(i,-1);
    }
    for(int i=1;i<=n;i++) 
    if(cut[i]) cutid++;
    cout<<cutid<<' '<<cutedge<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值