• 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;
    } 
  • 相关阅读:
    (转)SVN命令详解
    CentOS 64位系统安装32位兼容库
    Eclipse4.4 Tomcat插件下载地址
    记:Android 安装apk的代码实现
    记: Android adb远程调试
    记:Ubuntu14.04 Android加载项目失败
    记:Ubuntu 14.04 安装32位库支持库失败
    记:Android 服务站 问题记录与解决方案
    记:Android 知识点整理 20140329
    微信小程序和微信公众号的id是一个吗
  • 原文地址:https://www.cnblogs.com/lck-lck/p/9571556.html
Copyright © 2020-2023  润新知