zoukankan      html  css  js  c++  java
  • hoj 1520 The Bottom of a Graph // poj 2553 The Bottom of a Graph

    /*
    
    找到强连通分量变成缩点后求给出出度为0的所有点
    以下用tarjan算法做,第一个是用结构体的邻接链表来做,第二个使用的是vector作为邻接链表
    
    */
    #include <cstdio>
    #include <cstring>
    
    const int X = 15002;
    
    int dfn[X],low[X],stack[X],father[X],depth,top,bcnt;
    int counter[X],n,m;
    bool instack[X];
    
    struct node
    {
        int v;
        node *next;
        void fun()
        {
            v = 0;
            next = NULL;
        }
    }edge[X],*head[X],*tmp;
    
    void tarjan(int u)
    {
        int v;
        dfn[u] = low[u] = ++depth;
        stack[++top] = u;
        instack[u] = true;
    
        for(node *p=head[u];p;p=p->next)
        {
            v = p->v;
            if(!low[v])
            {
                tarjan(v);
                if(low[v]<low[u])
                    low[u] = low[v];
            }
            else if(instack[v]&&low[u]>dfn[v])
                low[u] = dfn[v];
        }
        if(low[u]==dfn[u])
        {
            bcnt++;
            do
            {
                v = stack[top--];
                instack[v] = false;
                father[v] = bcnt;
            }while(u!=v);
        }
    }
    
    void solve()
    {
        top = depth = bcnt = 0;
        memset(instack,false,sizeof(instack));
        memset(low,0,sizeof(low));
        memset(counter,0,sizeof(counter));
    
        for(int i=1;i<=n;i++)
            if(!low[i])
                tarjan(i);
    
        for(int i=1;i<=n;i++)
            for(node *p=head[i];p;p=p->next)
                if(father[i]!=father[p->v])
                    counter[father[i]]++;
        bool flag = false;
        for(int i=1;i<=n;i++)
            if(!counter[father[i]])
            {
                if(flag)
                    printf(" ");
                else
                    flag = true;
                printf("%d",i);
            }
        printf("\n");
    }
    
    int main()
    {
        freopen("sum.in","r",stdin);
        freopen("sum.out","w",stdout);
        int u,v;
        while(scanf("%d",&n),n)
        {
            scanf("%d",&m);
            memset(head,NULL,sizeof(head));
    
            for(int i=0;i<m;i++)
                edge[i].fun();
            tmp = edge;
            for(int i=0;i<m;i++)
            {
                scanf("%d%d",&u,&v);
                tmp->next = head[u];
                tmp->v = v;
                head[u] = tmp++;
            }
            solve();
        }
        return 0;
    }
    /*
    
    vector作为邻接链表
    
    */
    #include <vector>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int X = 15005;
    
    int dfn[X],low[X],father[X],stack[X],bcnt,top,depth;
    int counter[X],n,m;
    bool instack[X];
    vector<int> adj[X];
    
    void tarjan(int u)
    {
        low[u] = dfn[u] = ++depth;
        instack[u] = true;
        stack[++top] = u;
        int v,len = adj[u].size();
        for(int i=0;i<len;i++)
        {
            v = adj[u][i];
            if(!low[v])
            {
                tarjan(v);
                low[u] = min(low[u],low[v]);
            }
            else if(instack[v])
                low[u] = min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u])
        {
            ++bcnt;
            do
            {
                v = stack[top--];
                instack[v] = false;
                father[v] = bcnt;
            }while(u!=v);
        }
    }
    
    void solve()
    {
        depth = top = bcnt = 0;
        memset(low,0,sizeof(low));
        memset(instack,false,sizeof(instack));
        memset(counter,0,sizeof(counter));
    
        for(int i=1;i<=n;i++)
            if(!low[i])
                tarjan(i);
    
        int len;
        for(int i=1;i<=n;i++)
        {
            len = adj[i].size();
            for(int j=0;j<len;j++)
                if(father[i]!=father[adj[i][j]])
                    counter[father[i]]++;
        }
        bool flag = false;
        for(int i=1;i<=n;i++)
            if(!counter[father[i]])
            {
                if(flag)
                    printf(" ");
                else
                    flag = true;
                printf("%d",i);
            }
        printf("\n");
    }
    
    int main()
    {
        freopen("sum.in","r",stdin);
        freopen("sum.out","w",stdout);
        int u,v;
        while(scanf("%d",&n),n)
        {
            scanf("%d",&m);
            for(int i=1;i<=n;i++)
                adj[i].clear();
            for(int i=0;i<m;i++)
            {
                scanf("%d%d",&u,&v);
                adj[u].push_back(v);
            }
            solve();
        }
    
        return 0;
    }
  • 相关阅读:
    设计模式(三)原型模式
    PageHelper在Mybatis中的使用
    设计模式(二) 单例模式
    设计模式(一)简单工厂、工厂方法和抽象工厂
    Java网络编程
    循环控制语句if 、for、case、while
    处理海量数据的grep、cut、awk、sed 命令
    shell脚本的输入以及脚本拥有特效地输出
    shell的变量以及常见符号
    shell的使用技巧
  • 原文地址:https://www.cnblogs.com/yejinru/p/2508625.html
Copyright © 2011-2022 走看看