zoukankan      html  css  js  c++  java
  • Template

    【题目描述】

    给定一个无向图,询问图中存在多少个割点。

    【输入描述】

    第一行输入两个正整数N、M(N,M <= 50000),表示顶点数目和边数目;

    接下来M行,每行输入两个整数A、B,表示顶点A、B之间存在一条双向边。

    【输出描述】

    输出一个非负整数,表示答案。

    【输入样例】

    4 4

    1 2

    2 3

    3 4

    2 4

    【输出样例】

    1

    源代码:
    
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    struct Node
    {
        int To,Next;
    }Edge[100001]; //二倍大。
    int m,n,Sum(0),Num(0),Ans(0),i[50001],j[50001],Head[50001];
    bool Cut[50001];
    void Add(int t1,int t2) //边表。
    {
        Edge[++Sum].To=t2;
        Edge[Sum].Next=Head[t1];
        Head[t1]=Sum;
    }
    void Tarjan(int t,int Father) //Tarjan求桥割类。
    {
        int S(0);
        i[t]=j[t]=++Num;
        for (int a=Head[t];a;a=Edge[a].Next)
        {
            int T=Edge[a].To;
            if (!j[T])
            {
                S++;
                Tarjan(T,t);
                i[t]=min(i[t],i[T]);
                if (i[T]>=j[t]) //翻不到上方又是直连边,显而易见为割。
                  Cut[t]=true; //仔细想一下,为什么给Cut[t]赋值而不是Cut[T]。
            }
            else
              if (T!=Father)
                i[t]=min(i[t],j[T]);
        }
        if (S==1&&!Father) //防止两点的无效重复环。
          Cut[t]=false;
    }
    int main() //裸Tarjan求割点。
    {
        scanf("%d%d",&n,&m);
        for (int a=1;a<=m;a++)
        {
            int t1,t2;
            scanf("%d%d",&t1,&t2);
            Add(t1,t2);
            Add(t2,t1);
        }
        for (int a=1;a<=n;a++)
          if (!j[a])
            Tarjan(a,0);
        for (int a=1;a<=n;a++)
          if (Cut[a])
            Ans++;
        printf("%d",Ans);
        return 0;
    }
  • 相关阅读:
    高可用网站多点部署架构实战经验总结
    使用阿里云发送邮件完美解决 端口 25 465
    阿里云 SSL 证书 总结
    支付宝支付接入流程
    阿里云服务器ECS的环境部署和安装
    对接 第三方物流APP 手机版
    智付支付接入心得
    二次开发本地配置域名
    从1到n整数中1出现的次数:O(logn)算法
    MongoDB——增删改查
  • 原文地址:https://www.cnblogs.com/Ackermann/p/6005538.html
Copyright © 2011-2022 走看看