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;
    }
    
    
  • 相关阅读:
    Linux系统下ping命令报错 name or service not know
    利用Kettle进行SQLServer与Oracle之间的数据迁移实践
    STS中配置MyBatis代码生成器
    GeoServer中配置GeoWebCache切片缓存目录
    Win10下安装msi程序包时报2503、2502错误问题及其解决办法
    常用办公软件推荐
    Excel中使用VBA进行度分秒与十进制度的转换
    ArcGIS下图层范围不正确的两种处理方式
    更改GeoServer的端口号
    Tomcat跨域访问配置
  • 原文地址:https://www.cnblogs.com/liulangye/p/2529861.html
Copyright © 2011-2022 走看看