zoukankan      html  css  js  c++  java
  • poj 3352 双连通分量

    至少加几条边成为双连通分量

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int maxn=10000;
    struct
    {
        int to,next;
    }e[maxn];
    int head[maxn],lon;
    int dfn[maxn],instack[maxn],low[maxn],stack[maxn],s[maxn];
    int in[maxn];
    int count,top,con;
    int n,m;
    void edgemake(int from,int to,int head[])
    {
        e[++lon].to=to;
        e[lon].next=head[from];
        head[from]=lon;
    }
    void edgeini()
    {
        memset(head,-1,sizeof(head));
        lon=-1;
    }
    
    void tarjan(int t,int from)
    {
        dfn[t]=low[t]=++count;
        instack[t]=1;
        stack[++top]=t;
        for(int k=head[t];k!=-1;k=e[k].next)
        {
            if(k==(from^1)) continue;
            int u=e[k].to;
            if(dfn[u]==-1)
            {
                tarjan(u,k);
                low[t]=min(low[t],low[u]);
            }
            else if(instack[u])
            {
                low[t]=min(low[t],dfn[u]);
            }
        }
        if(dfn[t]==low[t])
        {
            ++con;
            while(1)
            {
                int u=stack[top--];
                instack[u]=0;
                s[u]=con;
                if(u==t) break;
            }
        }
    }
    
    void tarjan()//tarjan的初始化
    {
        memset(dfn,-1,sizeof(dfn));
        memset(instack,0,sizeof(instack));
        count=top=con=0;
        for(int i=1;i<=n;i++)
        if(dfn[i]==-1)
        tarjan(i,-1);
    }
    
    int main()
    {
        while(scanf("%d %d",&n,&m)!=EOF)
        {
            edgeini();
            for(int i=1,from,to;i<=m;i++)
            {
                scanf("%d %d",&from,&to);
                edgemake(from,to,head);
                edgemake(to,from,head);
            }
            tarjan();
            memset(in,0,sizeof(in));
            for(int i=1;i<=n;i++)
            for(int k=head[i];k!=-1;k=e[k].next)
            if(s[i]!=s[e[k].to])
            {
                in[s[i]]++;
            }
            int ans=0;
            for(int i=1;i<=con;i++)
            if(in[i]==1)
            ans++;
            else if(in[i]==0)
            ans+=2;
            if(con==1) ans-=2;
            printf("%d
    ",(ans+1)/2);
        }
        return 0;
    }
    


  • 相关阅读:
    C++实现高斯滤波器
    移动通信
    最简单的DLL
    C/C++ 编译和链接过程
    Servlet 详解
    对 Java 集合的巧妙利用
    Java 泛型
    Java 字符编码与解码
    HTTP 400 错误
    a 标签的四种样式
  • 原文地址:https://www.cnblogs.com/pangblog/p/3268571.html
Copyright © 2011-2022 走看看