zoukankan      html  css  js  c++  java
  • poj-3177(无向图缩点)

    题意:给你n个点,m条边的无向联通图,问你最少增加几条边,使得这个图每对点至少有两条路径

    解题思路:考虑每个环内的点必定有>=2条路径,所以先把这个无向图中的环去掉,用并查集缩环,然后剩下的图一定是个割边树,只需要把度为1的结点数/2就是答案了(把这棵树变成环);

    代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=100500;
    struct Edge
    {
        int next;int to;int id;
    }edge[maxn];
    int head[maxn],cnt,low[maxn],visit[maxn],dfn[maxn],step,ans,n,m;
    int f[maxn],x[maxn],y[maxn];
    int deg[maxn];
    void init()
    {
        memset(deg,0,sizeof(deg));
        memset(head,-1,sizeof(head));
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        for(int i=1;i<=n;i++)
            f[i]=i;
        cnt=step=0;
    }
    int findf(int u)
    {
        if(f[u]==u)
            return u;
        else
        {
            f[u]=findf(f[u]);
            return f[u];
        }
    }
    void join(int u,int v)
    {
        int t1=findf(u);int t2=findf(v);
        if(t2!=t1)
        {
            f[t2]=t1;
        }
    }
    void add(int u,int v,int id)
    {
        edge[cnt].next=head[u];edge[cnt].to=v;edge[cnt].id=id;head[u]=cnt++;
        edge[cnt].next=head[v];edge[cnt].to=u;edge[cnt].id=id;head[v]=cnt++;
    }
    void tarjan(int u,int fa)
    {
        dfn[u]=low[u]=++step;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            int id=edge[i].id;
            if(fa==id)
                continue;
            if(!dfn[v])
            {
                tarjan(v,id);
                low[u]=min(low[u],low[v]);
                if(dfn[u]<low[v])
                {
                    ans++;
                }
                else
                {
                    join(u,v);
                }
            }
            else
            {
                low[u]=min(low[u],dfn[v]);
            }
        }
    }
    int main()
    {
    
        scanf("%d%d",&n,&m);init();
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x[i],&y[i]);
            add(x[i],y[i],i);
        }
        tarjan(1,0);
        for(int i=1;i<=m;i++)
        {
            if(findf(x[i])==findf(y[i]))
                continue;
            else
            {
                deg[findf(x[i])]++;deg[findf(y[i])]++;
            }
        }
        int cot=0;
        for(int i=1;i<=n;i++)
        {
            if(deg[i]==1)
                cot++;
        }
        printf("%d
    ",(cot+1)/2);
    }
  • 相关阅读:
    MySQL笔记(6)---锁
    MySQL笔记(5)---索引与算法
    MySQL笔记(4)---表
    MySQL笔记(3)---文件
    MySQL笔记(2)---InnoDB存储引擎
    MySQL笔记(1)---MySQL体系结构和存储引擎
    生成器,迭代器,装饰器
    文件操作、def函数、模块导入、json
    数据类型、字符串操作
    基本数据类型,条件判断
  • 原文地址:https://www.cnblogs.com/huangdao/p/10631785.html
Copyright © 2011-2022 走看看