zoukankan      html  css  js  c++  java
  • poj3177重修道路——边双连通分量缩点

    题目:http://poj.org/problem?id=3177

    找桥,缩点,总之都是板子;

    对于每个叶子,互相连一条边即可;若最后剩下一个,则去和根节点连边;

    所以叶子节点数+1再/2即答案。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,m,ct=1,head[5005],reg[5005],c[5005],dc,dfn[5005],low[5005],tim,ans;
    bool bri[10005];
    struct N{
        int to,next;
        N(int t=0,int n=0):to(t),next(n) {}
    }edge[10005],dcc[10005];
    void tarjan(int x,int e)
    {
        tim++;
        dfn[x]=tim;
        low[x]=tim;
        for(int i=head[x];i;i=edge[i].next)
        {
            int u=edge[i].to;
    //        if(i==(e^1))continue;
            if(!dfn[u])
            {
                tarjan(u,i);
                low[x]=min(low[x],low[u]);
                if(low[u]>dfn[x])bri[i]=1,bri[i^1]=1;//!!!
            }
            else if(i!=(e^1))
                low[x]=min(low[x],dfn[u]);
        }
    }
    void dfs(int x)
    {
        c[x]=dc;
        for(int i=head[x];i;i=edge[i].next)
        {
            int u=edge[i].to;
            if(!c[u]&&!bri[i])
                dfs(u);
        }
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)==2)
        {
            memset(head,0,sizeof head);
            memset(reg,0,sizeof reg);
            memset(c,0,sizeof c);
            memset(dfn,0,sizeof dfn);
            memset(low,0,sizeof low);
            memset(bri,0,sizeof bri);
            ct=1;ans=0;dc=0;tim=0;
            for(int i=1;i<=m;i++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                edge[++ct]=N(y,head[x]);head[x]=ct;
                edge[++ct]=N(x,head[y]);head[y]=ct;
            }
            tarjan(1,0);
            for(int i=1;i<=n;i++)
            {
                if(c[i])continue;
                dc++;
                dfs(i);
            }
            for(int i=2;i<=ct;i+=2)
            {
                int u=edge[i].to,v=edge[i^1].to;
                if(c[u]==c[v])continue;
                reg[c[u]]++;reg[c[v]]++;
            }
            for(int i=1;i<=dc;i++)
                if(reg[i]==1)ans++;
            printf("%d
    ",(ans+1)/2);
        }
        return 0;
    }
  • 相关阅读:
    Educational Codeforces Round 6
    Codeforces Round #373 (Div. 2)
    尺取法
    Codeforces Round #542 [Alex Lopashev Thanks-Round] (Div. 2)
    逆元(数论倒数)
    最大公约数gcd,最小公倍数lcm,扩展欧几里得
    hdu 6395 Sequence (分段矩阵快速幂)
    快速幂
    hdu 6432 Cyclic
    hdu 6397 charactor encoding
  • 原文地址:https://www.cnblogs.com/Zinn/p/8667385.html
Copyright © 2011-2022 走看看