zoukankan      html  css  js  c++  java
  • poj 2186 Popular Cows 夜

    http://poj.org/problem?id=2186

    给你n头牛 他们之间会有一种 A认为B popular 的关系 而且这种关系是可传递的

    问你有多少头牛是被所有其他的牛认为popular

    1,缩点 将一个联通分量内的点缩成一个

    2,缩点同时记录联通分量内点的个数

    3,缩点后图变成了树 或者是 (非树)森林 如果是树 则树根连通分量内的点就是答案 如果是森林 答案为0

        生成的树或森林 根方向上是被指向的。

    4,由于3的原因 搜索时还有注意标记哪些缩点是没有可能成为根的缩点

    5,如果根缩点只有一个(树) 则根就是答案 如果多个(非树森林)则为0

    注意 Tarjan 搜索是并不一定一次就能将所有的点搜干净 注意这一点 想办法处理

    代码及其注释:

    #include<iostream>
    #include<cstring>
    #include<stack>
    #include<cstdio>
    #include<queue>
    
    using namespace std;
    
    const int N=10005;
    struct node
    {
        struct tt *next;
    }mem[N];
    struct tt
    {
        struct tt *next;
        int j;
    };
    int deep;
    int low[N];
    int dfn[N];
    bool visited[N];
    bool in[N];
    stack<int>str;
    int uppoint[N];
    int th[N];//第几次用Tarjan搜索
    bool f[N];//如果此点为其它缩点的父结点 所在联通分量不可能是根
    int sum[N];
    void build(int i,int j)
    {
        struct tt *t=new tt;
        t->j=j;
        t->next=mem[i].next;
        mem[i].next=t;
    }
    void Clearlist(int n)
    {
        struct tt *t;
        for(int i=1;i<=n;++i)
        {
            while(mem[i].next!=NULL)
            {
                t=mem[i].next;
                mem[i].next=t->next;
                delete t;
            }
        }
    }
    void Tarjan(int pre,int x,int ith)
    {
        ++deep;
        dfn[x]=low[x]=deep;
        th[x]=ith;//第几次使用Tarjan
        visited[x]=true;
        in[x]=true;
        str.push(x);
        struct tt *t=mem[x].next;
        bool think=false;
        while(t!=NULL)
        {
            if(visited[t->j]==false)
            {
                Tarjan(x,t->j,ith);
                low[x]=min(low[x],low[t->j]);
            }else if(in[t->j]==true)
            {
                low[x]=min(low[x],dfn[t->j]);
            }else if(th[t->j]<ith)//如果出现前几次用Tarjan搜过的点 则x所在的联通分量也不可能是根
            {
                think=true;
            }
            t=t->next;
        }
        if(think)
        {
            f[x]=true;
        }
        if(low[x]==dfn[x])
        {
            int num=0;
            while(str.top()!=x)
            {
                uppoint[str.top()]=x;//缩点
                in[str.top()]=false;
                ++num;
                str.pop();
            }
            uppoint[str.top()]=x;
            in[str.top()]=false;
            ++num;
            str.pop();
            sum[x]=num;
            f[pre]=true;//前一个点为父结点 不可能是根
        }
    }
    int main()
    {
        int n,m;
        while(scanf("%d %d",&n,&m)!=EOF)
        {
            while(m--)
            {
                int i,j;
                scanf("%d %d",&i,&j);
                build(i,j);
            }
            memset(th,-1,sizeof(th));
            memset(dfn,-1,sizeof(dfn));
            memset(visited,false,sizeof(visited));
            memset(in,false,sizeof(in));
            memset(f,false,sizeof(in));
            memset(uppoint,-1,sizeof(uppoint));
            memset(sum,0,sizeof(sum));
            deep=0;
            for(int i=1,t=1;i<=n;++i)
            {
                if(dfn[i]==-1)//防止一次搜不完 t 是第几次搜
                Tarjan(0,i,t++);
            }
            for(int i=1;i<=n;++i)
            {
                if(f[i])//把不可能是根联通分量的点的标记转移的缩点上
                f[uppoint[i]]=true;
            }
            int num=0;
            int k=0;
            for(int i=0;i<=n;++i)
            {
                if(i==uppoint[i]&&!f[i])
                {
                    ++num;
                    k=i;
                }
            }
            if(num!=1)//不只一个根联通分量
            {
                printf("0\n");
            }
            else
            {
                printf("%d\n",sum[k]);
            }
            Clearlist(n);
        }
        return 0;
    }
    
    
  • 相关阅读:
    (转)HTTP、TCP和HTTPS
    使用覆盖索引优化like查询
    Laravel 源码解析(一)
    redis 缓存策略注意的问题总结
    laravel 监听mysql操作 生成时间
    CommonJS, AMD, CMD 笔记
    php json_encode小数精度丢失的问题
    Python通过pandas操作excel常用功能
    Vmware 虚拟化技术
    磁盘中的esp分区与msr分区
  • 原文地址:https://www.cnblogs.com/liulangye/p/2529861.html
Copyright © 2011-2022 走看看