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;
            }
        }
    }
    不怕万人阻挡,只怕自己投降。
  • 相关阅读:
    HDU 3401 Trade
    POJ 1151 Atlantis
    HDU 3415 Max Sum of MaxKsubsequence
    HDU 4234 Moving Points
    HDU 4258 Covered Walkway
    HDU 4391 Paint The Wall
    HDU 1199 Color the Ball
    HDU 4374 One hundred layer
    HDU 3507 Print Article
    GCC特性之__init修饰解析 kasalyn的专栏 博客频道 CSDN.NET
  • 原文地址:https://www.cnblogs.com/newstartCY/p/11573279.html
Copyright © 2011-2022 走看看