• poj3177Redundant Paths tarjan缩点


    //给一个连通图,问最少须要加入多少条边才干使得
    //随意两个点都有两条不同的路走到
    //对于一个强连通分量的全部随意两点都能有两点能够到达
    //先用tarjan缩点,缩点以后就是一棵树,对于这个树考虑有几个
    //叶子节点 ans = (leaf+1)/2
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std ;
    const int maxn = 10010 ;
    int dfn[maxn] , low[maxn] , vis[maxn] ;
    int stack[maxn],isstack[maxn] , belong[maxn] ;
    int head[maxn] ;int n, m ;
    int step , nedge , num , top ;
    struct Edge
    {
        int v ;
        int next ;
    }edge[maxn<<1] ;
    void addedge(int u , int v)
    {
        edge[nedge].v = v ;
        edge[nedge].next = head[u]  ;
        head[u] = nedge++ ;
    }
    void init()
    {
        memset(head , - 1 , sizeof(head)) ;
        memset(dfn , 0 , sizeof(dfn)) ;
        memset(isstack , 0 , sizeof(isstack)) ;
        memset(vis , 0  ,sizeof(vis)) ;
        step = nedge = num = top = 0;
    }
    void tarjan(int u , int pre)
    {
        stack[++top] = u ;
        isstack[u] = 1 ;
        dfn[u] = low[u] = ++step;
        for(int i = head[u] ;i != -1 ;i = edge[i].next)
        {
           int v = edge[i].v ;
           if(pre == i)continue ;
           if(!dfn[v])
           {
               tarjan(v , i^1) ;
               low[u] = min(low[u] , low[v]) ;
           }
           else if(isstack[v])
           low[u] = min(low[u] , dfn[v]) ;
        }
        if(low[u] == dfn[u])
        {
            int v = -1 ;
            num++ ;
            while(u != v)
            {
                v = stack[top--] ;
                isstack[v] = 0 ;
                belong[v] = num ;
            }
        }
    }
    int main()
    {
        while(~scanf("%d%d" , &n , &m))
        {
            init() ;
            while(m--)
            {
                int u , v ;
                scanf("%d%d" , &u , &v) ;
                addedge(u , v) ;
                addedge(v, u) ;
            }
            tarjan(1, -1) ;
            for(int i = 1;i <= n;i++)
              for(int j = head[i] ; j != -1 ; j = edge[j].next)
              {
                  int u = belong[i] ;
                  int v = belong[edge[j].v] ;
                  if(u == v)continue ;
                  vis[u]++ ;
              }
            int ans = 0;
            for(int i = 1;i <= n;i++)
            if(vis[i] == 1)
            ans++ ;
            cout<<(ans+1)/2<<endl;
        }
    }
    
    
  • 相关阅读:
    K-Means算法总结
    C#设计模式(1)——单例模式
    sql 建表以及查询---复杂查询之成绩排名
    c# 折半查找法实现代码
    c# 合并两个有序数组
    C#中static void Main(string[] args)的含义
    C#中Main函数为什么要static
    C# 生成订单号的几种方式
    sql for xml path用法
    web端跨域调用webapi
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/7257258.html
Copyright © 2020-2023  润新知