zoukankan      html  css  js  c++  java
  • Tarjan算法(缩强连通子图为节点)

    //Tarjan算法(将强连通分量缩度再进行处理)  //POJ 2186
    #include<iostream>
    #include<cstdio>
    #include<stack>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn = 1e4 + 15;
    vector<int> Grape[maxn];
    int cnt;//缩度的节点个数
    int arr[maxn];//缩点的标号
    bool vis[maxn];
    int dfn[maxn],low[maxn],total;//total用来标序号
    int du[maxn];
    stack<int> s;
    void tarjan(int u)
    {
        dfn[u] = low[u] = ++total;
        s.push(u);
        vis[u] = true;//入栈
        for(int i=0;i!=Grape[u].size();++i)
        {
            int v = Grape[u][i];
            if(!dfn[v])
            {
                tarjan(v);
                low[u] = min(low[u],low[v]);
            }else if(vis[v])//如果在栈中存在
            {
                low[u] = min(low[u],dfn[v]);
            }
        }
        if(dfn[u]==low[u])//如果节点为强连通图的根
        {
            int v = 0;
            ++cnt;
            do{
                v = s.top();
                s.pop();
                vis[v] = false;
                arr[v] = cnt;
            }while(u!=v);
        }
    }
    int main()
    {
        int n,m;
        while(cin>>n>>m)//n个节点,m条边
        {
            for(int i=1;i<=n;++i)
                Grape[i].clear();
            int u,v;
            for(int i=1;i<=m;++i)
            {
                cin>>u>>v;
                Grape[u].push_back(v);
            }
            //Tarjan算法缩度
            cnt = 0,total = 0;
            memset(dfn,0,sizeof(dfn));
            memset(low,0,sizeof(low));
            memset(du,0,sizeof(du));//Judge node不为 0 的出度个数
            memset(arr,0,sizeof(arr));
            for(int u=1;u<=n;++u)
            {
                if(!dfn[u])
                {
                    tarjan(u);
                }
            }
            for(int u=1;u<=n;++u)
            {
                for(int i=0;i!=Grape[u].size();++i)
                {
                    int v = Grape[u][i];
                    if(arr[u]!=arr[v])
                        ++du[arr[u]];//u 节点所在的环
                }
            }
            int num = 0,pos = 0;
            for(int v=1;v<=cnt;++v)
            {
                if(du[v]==0)
                {
                    ++num;
                    pos = v;
                }
            }
            if(num!=1)
                cout<<0<<endl;
            else{
                int ans = 0;
                for(int i=1;i<=n;++i)
                    if(arr[i]==pos)
                        ++ans;
                cout<<ans<<endl;
            }
        }
    }
    不怕万人阻挡,只怕自己投降。
  • 相关阅读:
    Nginx配置中运行与启动的详细介绍
    php实现文件上传进度条
    C# 提取逗号分割的字符串
    【sas proc sql】out join
    【SAS NOTE】substr函数
    【sas proc sql】子查询
    【SAS NOTE】数字字符互换
    【SAS NOTE】数组
    【sas Notel】merge
    【sas sql proc】inner join or outer join
  • 原文地址:https://www.cnblogs.com/newstartCY/p/11573279.html
Copyright © 2011-2022 走看看