• 构造双连通(tarjan)


    题目:

    给定一个N个顶点,M条边的无向连通图,顶点从1到N编号。

    问至少要添加几条边,才能使其变为双连通图。

    输入

    第一行包含两个整数N, M (3 le N, M le 1000)N,M(3N,M1000)。

    接下来M行,每行两个整数u, v(1 le u, v le N)u,v(1u,vN),表示u, vu,v之间一条无向边相连。

    输入保证是一个连通图。

    输出

    输出最少添加几条边使得其变成双连通图。

    样例

    输入

    复制
    10 12
    1 2
    1 3
    1 4
    2 5
    2 6
    5 6
    3 7
    3 8
    7 8
    4 9
    4 10
    9 10

    输出

    2

    输入

    3 3
    1 2
    2 3
    1 3

    输出

    0
    /*************************************************************************
      > Author: Henry Chen
      > Mail: 390989083@qq.com 
     ************************************************************************/
    
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 5005;
    
    int head[maxn],nxt[maxn*2],tot;
    int n,m;
    int flag[maxn];
    int low[maxn],dfn[maxn];
    int st[maxn],inst[maxn];
    int tp;
    int tt,cnt;
    int f[maxn];
    
    struct edge
    {
        int v;
        bool ck;
    }e[maxn*2];
    
    void add_edge(int u,int v)
    {
        e[tot].v = v;
        e[tot].ck = false;
        nxt[tot] = head[u];
        head[u] = tot;
        tot++;
    }
    
    void tarjan(int u,int fa)
    {
        //cout << u << endl;
        dfn[u] = low[u] = ++tt;
        st[tp++] = u;
        inst[u] = 1;
        for(int i = head[u];i != -1;i = nxt[i])
        {
            int v = e[i].v;
            //printf("%d %d
    ",v,dfn[v]);
            if(v == fa) continue;
            if(!dfn[v])
            {
                tarjan(v,u);
                if(low[u] > low[v])
                {
                    low[u] = low[v];
                }
                if(dfn[u] < low[v])
                {
                    e[i].ck = true;
                    e[i^1].ck = true;
                }
            }
            else if(inst[v] && low[u] > dfn[v])
            {
                low[u] = dfn[v];
            }
        }
        if(low[u] == dfn[u])
        {
            int v;
            cnt++;
            v = st[--tp];
            inst[v] = 0;
            f[v] = cnt;
            while(u != v)
            {
                v = st[--tp];
                inst[v] = 0;
                f[v] = cnt;
            }
        }
    }
    
    
    int main()
    {
        cin >> n >> m;
        memset(head,-1,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(inst,0,sizeof(inst));
        memset(flag,0,sizeof(flag));
        tot = 0;
        for(int i = 1;i <= m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add_edge(u,v);
            add_edge(v,u);
        }
        tp = 0;
        tt = 0;
        cnt = 0;
        tarjan(1,1);
        for(int u = 1;u <= n;u++)
        {
            for(int i = head[u];i != -1;i = nxt[i])
            {
                //printf("%d %d
    ",i,e[i].ck);
                if(e[i].ck)
                {
                    flag[f[u]]++;
                }
            }
        }
        int ans = 0;
        for(int i = 1;i <= cnt;i++)
        {
            if(flag[i] == 1)
            {
                ans++;
            }
        }
        printf("%d
    ",(ans+1)/2);
        return 0;
    }
  • 相关阅读:
    使用netty实现im聊天
    使用rabbitmq实现集群im聊天服务器消息的路由
    springcloud feign使用
    10万用户一年365天的登录情况如何用redis存储,并快速检索任意时间窗内的活跃用户
    redis的rdb与aof持久化机制
    springcloud-zinpin的安装与使用
    kafka的基本安装与使用
    RabbitMq 实现延时队列-Springboot版本
    RabbitMq 基本命令
    Dcoker 安装 rabbitMq
  • 原文地址:https://www.cnblogs.com/mzyy1001/p/13605082.html
Copyright © 2020-2023  润新知