• poj2186强连通分量


    这题。。。。。。。做了半天,倒是让我更加了解了强连通分量,是我的第二道强连通。

    石建让我做一下这道题,我用模板再变形,改了很久之后,能给出的样例都过了。

    discussion上的样例都过了,倒是上面N多人说数据没过AC了。。。。。

    你让我们这数据过了没AC的生活如何自理。。。

    先放着,哪天有思路再来搞。。

    /////////////重新做了一遍,发现之前的思路太乱了,整理之后水过了、、、、、、、、、、、、、

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    using namespace std;
    
    #define MAXN 50010
    #define MAXM 100010
    
    struct Edge
    {
          int v, next;
    }edge[MAXM];    //边结点数组
    
    int num[MAXN];
    int first[MAXN], stack[MAXN], DFN[MAXN], Low[MAXN], Belong[MAXM];
    // first[]头结点数组,stack[]为栈,DFN[]为深搜次序数组,Belong[]为每个结点所对应的强连通分量标号数组
    // Low[u]为u结点或者u的子树结点所能追溯到的最早栈中结点的次序号
    int instack[10010];  // instack[]为是否在栈中的标记数组
    int n, m, cnt, scnt, top, tot;
    
    void init()
    {
        cnt = 0;
        scnt = top = tot = 0;    //初始化连通分量标号,次序计数器,栈顶指针为0
        memset(first, -1, sizeof(first));
        memset(DFN, 0, sizeof(DFN));   //结点搜索的次序编号数组为0,同时可以当是否访问的数组使用
    }
    
    void read_graph(int u, int v) //构建邻接表
    {
         edge[tot].v = v;
         edge[tot].next = first[u];
         first[u] = tot++;
    }
    
    void Tarjan(int v)       //Tarjan算法求有向图的强连通分量
    {
         int min, t;
         DFN[v] = Low[v] = ++tot;    //cnt为时间戳
         instack[v] = 1;    //标记在栈中
         stack[top++] = v;      //入栈
         for(int e = first[v]; e != -1; e = edge[e].next)
         {   //枚举v的每一条边
               int j = edge[e].v;   //v所邻接的边
               if(!DFN[j])
               {   //未被访问
                   Tarjan(j);    //继续向下找
                   if(Low[v] > Low[j]) Low[v] = Low[j];  // 更新结点v所能到达的最小次数层
               }
               else if(instack[j] && DFN[j] < Low[v])
               {   //如果j结点在栈内,
                   Low[v] = DFN[j];
               }
         }
         if(DFN[v] == Low[v])
         {     //如果节点v是强连通分量的根
               scnt++;   //连通分量标号加1
               do
               {
                   t = stack[--top];   //退栈
                   instack[t] = 0;   //标记不在栈中
                   Belong[t] = scnt;   //出栈结点t属于cnt标号的强连通分量
                   num[scnt]++;
    
               }while(t != v);  //直到将v从栈中退出
         }
    }
    
    void solve()
    {
         for(int i = 1; i <= n; i++)   //枚举每个结点,搜索连通分量
            if(!DFN[i])  //未被访问
               Tarjan(i);  //则找i结点的连通分量
    }
    int b1[MAXN],b2[MAXN];
    int outdegree[MAXN];
    int main()
    {
        scanf("%d%d",&n,&m);
    
            init();
            int temp=1;
            int m1=m;
            memset(num,0,sizeof(num));
            memset(outdegree,0,sizeof(outdegree));
            while(m--)
            {
                int u, v;
                scanf("%d%d", &u, &v);
                b1[temp]=u;b2[temp++]=v;
                read_graph(u, v);
            }
            solve();     //求强连通分量
            for(int i=1;i<=m1;i++)
            {
                if(Belong[b1[i]]!=Belong[b2[i]])
                outdegree[Belong[b1[i]]]++;
            }
            int tmp=0;int k=0;
            for(int i=1;i<=scnt;i++)
            {
                //cout<<outdegree[i]<<endl;
                if(outdegree[i]==0)
                    {tmp++;k=i;}
            }
            if(tmp>1)
            {
                cout<<0<<endl;
            }
            else if(tmp==1)
            {
                cout<<num[k]<<endl;
            }
    
        return 0;
    }
    

  • 相关阅读:
    手撸编译器(2)...
    手撸编译器(1)...
    语义分析(2)...
    【最大流】ECNA 2015 F Transportation Delegation (Codeforces GYM 100825)
    【模拟】CSU 1807 最长上升子序列~ (2016湖南省第十二届大学生计算机程序设计竞赛)
    【宽搜】ECNA 2015 D Rings (Codeforces GYM 100825)
    【宽搜】ECNA 2015 E Squawk Virus (Codeforces GYM 100825)
    【模拟】ECNA 2015 I What's on the Grille? (Codeforces GYM 100825)
    【最短路】【数学】CSU 1806 Toll (2016湖南省第十二届大学生计算机程序设计竞赛)
    【树状数组】CSU 1811 Tree Intersection (2016湖南省第十二届大学生计算机程序设计竞赛)
  • 原文地址:https://www.cnblogs.com/amourjun/p/5134164.html
Copyright © 2020-2023  润新知