zoukankan      html  css  js  c++  java
  • poj 2186 tarjan求强连通分量

    蕾姐讲过的例题..玩了两天后才想起来做 貌似省赛之后确实变得好懒了...再努力两天就可以去北京玩了!

    顺便借这个题记录一下求强连通分量的算法 

    1 只需要一次dfs 依靠stack来实现的tarjan算法 每次走到一个点 马上把它压入栈中 每次对与这个点相连的点处理完毕 判断是否low[u]==dfn[u] 若是 开始退栈 直到栈顶元素等于u才退出(当栈顶元素等于u也需要pop) 每次一起退栈的点属于同一个强连通分量 储存图可以用链式前向星也可以用邻接矩阵更可以用vector 蕾姐说不会超时 我信了

    2 需要两次dfs的kosara 在输入图的时候需要搞出来一个反向图以便第二次dfs使用 开始进行一次dfs 每当一个点要离开的时候就将其压入栈中 当所有的点都被遍历后 从栈顶元素开始进行反向搜索 一次搜到的点属于同一个强连通分量 其实..也需要用到栈...

    需要注意的是 当使用tarjan时 dfs时如果判断dfn[v]时已经有了值 在else中需要有if条件(!id[v]) 

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<math.h>
    #include<iostream>
    #include<stack>
    #include<vector>
    using namespace std;
    int n,m;
    int id[10050];
    int dfn[10050];
    int low[10050];
    int ans[10050];
    int cd[10050];
    int point[10050];
    int num;
    int cnt;
    int tot;
    vector<int >q[10050];
    stack<int >s;
    void init(){
    for(int i=1;i<=n;i++)
    {
        id[i]=0;
        dfn[i]=0;
        low[i]=0;
        ans[i]=0;
        cd[i]=0;
        point[i]=-1;
        q[i].clear();
    }
    num=cnt=tot=0;
    while(!s.empty())
        s.pop();
    }
    void dfs(int u){
        dfn[u]=low[u]=++cnt;
        s.push(u);
        int v;
        int siz=q[u].size();
        for(int i=0;i<siz;i++)
        {
            v=q[u][i];
            if(!dfn[v])
            {
                dfs(v);
                low[u]=min(low[u],low[v]);
    
            }
            else if(!id[v])
            {
                low[u]=min(low[u],dfn[v]);
            }
        }
        if(low[u]==dfn[u])
        {
            int temp=0;
            num++;
            while(!s.empty())
            {
                int v=s.top();
                s.pop();
                temp++;
                id[v]=num;
                if(v==u)
                    break;
            }
            ans[num]=temp;
        }
    }
    struct node
    {
        int v,nex;
    };
    node a[10050];
    void add(int u,int v)
    {
        a[tot].v=v;
        a[tot].nex=point[u];
        point[u]=tot;
        tot++;
    }
    void jt(){
    for(int i=1;i<=n;i++)
    {
        int siz=q[i].size();
        for(int k=0;k<siz;k++)
        {
            int v=q[i][k];
            if(id[v]!=id[i])
            {
                cd[id[i]]++;
            }
        }
    }
    }
    void did(){
    int can=0;
    int p=-1;
    for(int i=1;i<=num;i++)
    {
        if(cd[i]==0)
        {
            can++;
            p=i;
        }
    }
    if(can==1)
    {
        printf("%d
    ",ans[p]);
    }
    else
        printf("0
    ");
    }
    int main(){
    while(cin>>n>>m)
    {
        init();
        for(int i=1;i<=m;i++)
        {
            int u,v;
            cin>>u>>v;
            q[u].push_back(v);
        }
        for(int i=1;i<=n;i++)
        {
            if(!dfn[i])
                dfs(i);
        }
        jt();
        did();
    }
    }
    

      

  • 相关阅读:
    让DateTimePicker显示空时间值 (转) 武胜
    Webcam in C#: AForge.NET (转) 武胜
    C#自定义事件的步骤 武胜
    交换机VLAN的配置 (转) 武胜
    虚拟LAN安全的最佳实践经验 (转) 武胜
    绿色版 MySQL 的安装配置 (转) 武胜
    net 中捕获摄像头视频的方式及对比(How to Capture Camera Video via .Net) (转) 武胜
    C# WndProc的使用方法 (转) 武胜
    金融证券业Windows NT服务器热备份系统工作示意图 (转) 武胜
    ubuntu下配置samba实现文件夹共享
  • 原文地址:https://www.cnblogs.com/rayrayrainrain/p/5516038.html
Copyright © 2011-2022 走看看