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;
    }
  • 相关阅读:
    linux基础知识之vi编辑器的使用
    Linux的通信命令
    Linux学习之文件的压缩与解压
    Liux文件操作
    Linux简单学习
    Drupal V7.3.1 框架处理不当导致SQL注入
    Typecho V1.1反序列化导致代码执行分析
    浅析PHP反序列化漏洞之PHP常见魔术方法(一)
    python正则表达式记录
    SQLmap源码分析之框架初始化(一)
  • 原文地址:https://www.cnblogs.com/Ackermann/p/6005538.html
Copyright © 2011-2022 走看看