zoukankan      html  css  js  c++  java
  • P1536 村村通

    传送门

    本题的标算是并查集查找连通块的个数,为了练习下Tarjan,就用Tranjan写一波;

    思路:tarjan

    观察题目,市政府“村村通工程”的目标是使全市任何两个城镇间都可以实现交通,表明图为多个联通块,因为是无向边,所以每个联通块一定是一个强连通分量(显然)。

    那么问题就变成了 查找联通块,将所有联通块联通,显然需要n-1条边。

    所以 只需要tarjan搜索强连通分量的个数,然后输出强连通分量个数减一即为答案。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=100005;
    int n,m;
    vector<int> G[MAXN];//试一下动态存图
    int dfn[MAXN],low[MAXN],cnt=0,index_=0;
    int scc[MAXN],size[MAXN];
    bool inStack[MAXN];
    stack<int> st;
    void tarjan(int u)
    {
        index_++;
        dfn[u]=index_;
        low[u]=index_;
        st.push(u);
        inStack[u]=true;
        for(int i=0;i<G[u].size();i++)
        {
            if(!dfn[G[u][i]])
            {
                tarjan(G[u][i]);
                low[u]=min(low[u],low[G[u][i]]);
            }
            else if(inStack[G[u][i]])
                low[u]=min(low[u],dfn[G[u][i]]);
        }
        if(low[u]==dfn[u])
        {
            cnt++;
            while(st.top()!=u)
            {
                scc[st.top()]=cnt;
                size[cnt]++;
                inStack[st.top()]=false;
                st.pop();
            }
            scc[st.top()]=cnt;
            size[cnt]++;
            inStack[st.top()]=false;
            st.pop();
        }
    }
    inline void clear()
    {
        for(int i=0;i<=MAXN;i++)
        G[i].clear();
        cnt=0;
        memset(scc,0,sizeof(scc));
        memset(inStack,0,sizeof(inStack));
        memset(size,0,sizeof(size));
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        while( !st.empty() )
          st.pop();
        index_=0;
    }
    int main()
    {
        ios::sync_with_stdio(0);   //syn加速
        for(;;)
        {
            clear();
            cin>>n;
            if(n==0) break;
            cin>>m;
            for(int i=0;i<m;i++)
               {
                int x,y;
                cin>>x>>y;
                G[x].push_back(y);
                G[y].push_back(x);
            }
            for(int i=1;i<=n;i++)
                if(!dfn[i])
                    tarjan(i);
            cout<<cnt-1<<endl;        
        }
    return 0;
    } 
  • 相关阅读:
    curl.class.php方便使用
    php发送邮件
    php部分被弃用方法的代替方法
    正则表达式匹配
    php xml常用函数的集合及四种方法
    PHP5中使用PDO连接数据库的方法
    http协议的状态码
    MySQL数据库中的Date,DateTime和TimeStamp类型
    php中json_decode()和json_encode()的使用方法
    UIIabel自适配高度
  • 原文地址:https://www.cnblogs.com/lck-lck/p/9571556.html
Copyright © 2011-2022 走看看