zoukankan      html  css  js  c++  java
  • Tarjan算法(缩点)

    因为最近在学2sat,需要学习前置技能—Tarjan算法,所以花了一天的时间学习这个算法

    算法步骤:

    1.从一个点开始dfs,并加入栈

    2.如果下一个点没有到过,跳到第一步

    3.如果下一个点到过,并且在栈中,下一个点到这个点,这一段构成一个回路,也就是可以缩点

    具体实现

    void dfs(int x)
    {
        st.push(x);      //加入栈
        dis[x]=1;        //x点在栈中
        dfn[x]=low[x]=++te;    //dfn用来表示某个点访问过,并且记录初始的low值
        for(int i=f[x]; i; i=nex[i])
        {
            int v=to[i];
            if(dfn[v]==0)
            {
                dfs(v);
                low[x]=min(low[x],low[v]);   //将一个回路的low改成一样的
            }
            else if(dis[v]==1)low[x]=min(low[x],low[v]);    //下一个点在栈中,那么找到一个回路,但是可能是嵌套回路,所以取最小low
        }
        if(dfn[x]==low[x])   //表示x点的初始值没有被改变,构成一个强连通分量
        { 
            while(st.size())
            {
                int g=st.top();
                st.pop();
                dis[g]=0;
                id[g]=x;    //用x命名强连通分量
                if(g==x)break;  //代表g是强连通分量的最后一个数
            }
        }
    }
    

    题目:poj2186

    题解:先缩点,然后构成一个新的图,找到出度为一的一个被缩过的点,返回这个点的数量,如果有1个以上被缩过的点出度为0,那么返回0

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <ctime>
     5 #include <cstdlib>
     6 #include <vector>
     7 #include <stack>
     8 using namespace std;
     9 #define ll long long
    10 const int maxn=1e4+10;
    11 const int maxm=5e4+10;
    12 int f[maxn],nex[maxm],to[maxm],cnt,ot[maxm];
    13 int dfn[maxn],low[maxn],id[maxn],te;
    14 vector<int>ve;
    15 stack<int>st;
    16 int ma[maxn];
    17 bool dis[maxn];
    18 void add(int a,int b)
    19 {
    20     cnt++;
    21     to[cnt]=b;
    22     nex[cnt]=f[a];
    23     f[a]=cnt;
    24     ot[cnt]=a;
    25 }
    26 void dfs(int x)
    27 {
    28     st.push(x);
    29     dis[x]=1;
    30     dfn[x]=low[x]=++te;
    31     for(int i=f[x]; i; i=nex[i])
    32     {
    33         int v=to[i];
    34         if(dfn[v]==0)
    35         {
    36             dfs(v);
    37             low[x]=min(low[x],low[v]);
    38         }
    39         else if(dis[v]==1)low[x]=min(low[x],low[v]);
    40     }
    41     if(dfn[x]==low[x])
    42     {
    43         ve.push_back(x);
    44         while(st.size())
    45         {
    46             int g=st.top();
    47             st.pop();
    48             dis[g]=0;
    49             id[g]=x;
    50             if(g==x)break;
    51         }
    52     }
    53 }
    54 int main()
    55 {
    56     int n,m;
    57     scanf("%d %d",&n,&m);
    58     for(int i=1; i<=n; i++)id[i]=i;
    59     for(int i=1; i<=m; i++)
    60     {
    61         int a,b;
    62         scanf("%d %d",&a,&b);
    63         add(a,b);
    64     }
    65     for(int i=1; i<=n; i++)
    66         if(dfn[i]==0)dfs(i);
    67     for(int i=1; i<=cnt; i++)
    68     {
    69         int a=id[to[i]];
    70         int b=id[ot[i]];
    71         if(a!=b)
    72             ma[b]++;
    73     }
    74     int fla=0,num=0;
    75 
    76     for(int i=0; i<ve.size(); i++)
    77     {
    78         if(ma[ve[i]]==0)num++,fla=ve[i];
    79     }
    80     if(ve.size()==1)num=1,fla=ve[0];
    81     if(num==1)
    82     {
    83         int ans=0;
    84         for(int i=1; i<=n; i++)
    85             if(id[i]==fla)ans++;
    86         printf("%d
    ",ans);
    87     }
    88     else
    89         printf("0
    ");
    90     return 0;
    91 }
  • 相关阅读:
    1.3.6 详解build.gradle文件——Android第一行代码(第二版)笔记
    1.3.5 详解项目中的资源——Android第一行代码(第二版)笔记
    1.3.4分析你的第一个Android程序——Android第一行代码(第二版)笔记
    1.3创建你的第一个Android项目——Android第一行代码(第二版)笔记
    1.2搭建开发环境——Android第一行代码(第二版)笔记
    1.1.3 Android应用开发特色——Android第一行代码(第二版)笔记
    函数与方法的区别
    你真的知道敏捷到底是什么吗?
    某个应用的CPU使用率居然达到100%,我该怎么办?
    异常 lock buffer failed for format 0x23
  • 原文地址:https://www.cnblogs.com/carcar/p/9733200.html
Copyright © 2011-2022 走看看