zoukankan      html  css  js  c++  java
  • poj2553 有向图缩点,强连通分量。

    //求这样的sink点:它能达到的点,那个点必能达到他,即(G)={v∈V|任意w∈V:(v→w)推出(w→v)}
    //我法:tarjan缩点后,遍历点,如果该点到达的点不在同一个强连通中,该点排除,而且该点所在的
    //的强连通分支所有点都排除(开始因为这个跪WA!慎思!)
    #include<iostream>   //143MS,
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<stack>
    #include<queue>
    using namespace std;
    int n;int m;
    const int MAX=5001;
    vector<vector<int> >edges(MAX);
    int visited[MAX];
    int low[MAX];
    int dfn[MAX];
    int is_sink[MAX];          //统计出入度
    int Strongly_connected_branch[MAX];  //并为一个强连通,标记为1.2.3...
    int num;int times;
    bool is_sink_all[MAX];
    stack<int>s;
    bool instack[MAX];
    void tarjan(int u)
    {
        low[u]=dfn[u]=times++;
        instack[u]=1;
        s.push(u);
        int len=edges[u].size();
        for(int i=0;i<len;i++)
        {
            int v=edges[u][i];
            if(visited[v]==0)          //小心细节!
            {
                 visited[v]=1;
                   tarjan(v);
                if(low[u]>low[v])low[u]=low[v];
            }
            else if(instack[v]&&low[u]>dfn[v])     //有向图,要问是否在栈中,后向边,V为U某个祖先
            {
                low[u]=dfn[v];
            }
        }
        if(dfn[u]==low[u])         //在一个SCC
        {
            num++;int temp;
             do
            {
                 temp=s.top();
                 instack[temp]=0;
                s.pop();
                Strongly_connected_branch[temp]=num;
            } while(temp!=u);
        }
    }
    void initialize()
    {
        num=times=0;
        for(int i=0;i<=n;i++)
        {
            instack[i]=low[i]=dfn[i]=visited[i]=0;
            edges[i].clear();
            is_sink_all[i]=is_sink[i]=1;
            Strongly_connected_branch[i]=-1;
        }
    }
    bool readin()
    {
        scanf("%d",&n);
        if(n==0)return 0;
        scanf("%d",&m);
        initialize();
        int from,to;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&from,&to);
            edges[from].push_back(to);
        }
        return 1;
    }
    void solve()
    {
        for(int i=1;i<=n;i++)
           if(visited[i]==0)
            {
                visited[i]=1;
                tarjan(i);
            }
         for(int i=1;i<=n;i++)     //自己思得:枚举所有边,缩点只是把所有SCC分开
       {                           
          int len=edges[i].size();
           for(int j=0;j<len;j++)
           {
              int v=edges[i][j];
              if(Strongly_connected_branch[v]!=Strongly_connected_branch[i])//b不再用一个强连通分支
              {
                is_sink[i]=0;          
                is_sink_all[Strongly_connected_branch[i]]=0; //其所在强连通全跪!
                break;
              }
           }
        }
        queue<int>q;       //要按顺序输出,无奈。
        for(int i=1;i<=n;i++)
        {
           if(is_sink_all[Strongly_connected_branch[i]]==0){continue;}
           if(is_sink[i]==1)q.push(i);
        }
        while(!q.empty())
        {
            int cur=q.front();
            if(q.size()==1)printf("%d
    ",cur);
            else printf("%d ",cur);
            q.pop();
        }
    }
    int main()            //代码越来越清楚O(∩_∩)O~
    {
       while(readin())
       {
           solve();
       }
       return 0;
    }
    
    

  • 相关阅读:
    JavaScript中的变量及数据类型
    EasyUI——常见用法总结
    MVC页面重定向'页面跳转
    window.location.href的用法
    MVC JsonResult的用法
    Knockoutjs快速入门(经典)
    Knockoutjs的环境搭建教程
    4位双扫描、8位单扫描
    存储周期(存取周期)
    c语言中static、extern、void的重载
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925815.html
Copyright © 2011-2022 走看看