zoukankan      html  css  js  c++  java
  • poj-3177(并查集+双联通分量+Tarjan算法)

    题目链接:传送门

    思路:

    题目要将使每一对草场之间都有至少两条相互分离的路径,所以转化为(一个有桥的连通图至少加几条边才能变为双联通图?)

    先求出所有的桥的个数,同时将不同区块收缩成一个点(利用并查集),之后一个图变为了一颗树;

    然后在统计树中度数为1的点的个数,记为cnt,则至少添加(cnt+1)/2条边。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int maxn = 10010;
    struct Edge{
        int u,v;
    };
    Edge tmp;
    vector <Edge> ee;
    int num[maxn],vis[maxn],low[maxn],fa[maxn],tog[maxn],m,n,tim;
    vector <int> vc[maxn];
    void Init()
    {
        memset(vis,0,sizeof(vis));
        memset(num,0,sizeof(num));
        memset(low,0,sizeof(low));
        memset(fa,0,sizeof(fa));
        memset(tog,0,sizeof(tog));
        ee.clear();
        for(int i=0;i<maxn;i++) vc[i].clear();
        tim=1;
    }
    int MIN(int x,int y)
    {
        return x<y?x:y;
    }
    int f(int x)
    {
        if(fa[x]==0) return x;
        else return fa[x]=f(fa[x]);
    }
    void Tarjan(int v,int pre)
    {
        int i,w;
        vis[v]=1;
        low[v]=num[v]=tim++;
        for(i=0;i<vc[v].size();i++){
            w=vc[v][i];
            if(!vis[w]){
                Tarjan(w,v);
                low[v]=MIN(low[v],low[w]);
                if(low[w]>num[v]){ //找到桥 
                    tmp.u=v;tmp.v=w;
                    ee.push_back(tmp);
                }
                else{ //不是桥,就缩点 
                    int t1=f(v);
                    int t2=f(w);
                    if(t1!=t2) fa[t2]=t1;
                }
            }
            else if(pre!=w) low[v]=MIN(low[v],num[w]); 
        }
    }
    int main(void)
    {
        int i,j,x,y;
        while(~scanf("%d%d",&n,&m)){
            Init();
            for(i=0;i<m;i++){
                scanf("%d%d",&x,&y);
                vc[x].push_back(y);
                vc[y].push_back(x);
            }
            Tarjan(1,-1);
            for(i=0;i<ee.size();i++){ //统计树中的度数为1的顶点的个数 
                int t1=f(ee[i].u);
                int t2=f(ee[i].v);
                tog[t1]++;tog[t2]++;
            }
            int cnt=0;
            for(i=1;i<=n;i++)
            if(tog[i]==1) cnt++;
            cnt=(cnt+1)/2;
            printf("%d
    ",cnt);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    jekins 实现Django项目的自动部署(ubuntu16.04,python2.7,django1.11)
    Ubuntu16.04 安装 Django
    小米笔记本 air 12.5寸 支持硬盘参数
    editplus5激活码
    jmeter UDV
    c语言 快速排序
    html禁止文本输入框记录输入记录,单击input出现输入过的记录
    python pstats ,profile 性能分析
    python profile性能分析
    python 获取本地语言和编码的代码
  • 原文地址:https://www.cnblogs.com/2018zxy/p/10357599.html
Copyright © 2011-2022 走看看