• POJ 2186 Popular Cows tarjan缩点算法


      题意:给出一个有向图代表牛和牛喜欢的关系,且喜欢关系具有传递性,求出能被所有牛喜欢的牛的总数(除了它自己以外的牛,或者它很自恋)。

      思路:这个的难处在于这是一个有环的图,对此我们可以使用tarjan算法求出强连通分量,把强连通分量压缩成一个点,构成一个新的图,这个图一定是没有环的,如果有环就跟强连通分量的矛盾了。压缩成无环图以后这个图里面的点是不具有方向的,我们通过遍历每个节点所能连到的点,如果两点的id值即所在的强连通分量区域不同时,我们就把这个节点的出度加1。最后去找那些出度等于0的点,如果没有或者超过1,那这图的答案是0,因为如果有两个点他们的出度都是0,那么意味着这两个点之间没有关系,所以地图中不可能出现一头牛被所有的牛喜欢。

      需要注意的地方,在一开始我的连通分量的id记录出错了,原因是我的第一个点在主函数里入栈,导致有些点没有被记录。后来受无向图的惯性思维的影响,又把判断pa != v的条件加上了,这个是有向图,是绝对不可以加这个判定的!具体代码如下:

    #include<cstdio>
    #include<stack>
    #include<cstring>
    #include<iostream>
    using namespace std;
    #define maxn 10010
    struct EDGE
    {
        int to,nxt;
    } edge[maxn*5];
    int head[maxn],id[maxn],dfn[maxn],low[maxn],tot,sum;
    stack<int> s;
    int all[maxn];
    void tarjan(int u,int fa)
    {
        s.push(u);
        dfn[u] = low[u] = ++tot;
        for(int i = head[u]; i != -1; i = edge[i].nxt)
        {
            int v = edge[i].to;
            if(!dfn[v])
            {
                tarjan(v,u);
                low[u] = min(low[v],low[u]);
            }
            else if(!id[v]) low[u] = min(low[u],dfn[v]);
        }
        if(low[u] == dfn[u])
        {
            sum++;
            while(!s.empty())
            {
                int num = s.top();
                s.pop();
                id[num] = sum;
                all[sum]++;
                if(u == num) break;
            }
        }
        return ;
    }
    int main()
    {
        int n,m,x,y;
        while(~scanf("%d%d",&n,&m))
        {
            memset(head,-1,sizeof(head));
            for(int i = 0; i < m; i++)
            {
                scanf("%d%d",&x,&y);
                edge[i].to = y;
                edge[i].nxt = head[x];
                head[x] = i;
            }
            memset(dfn,0,sizeof(dfn));
            memset(low,0,sizeof(low));
            memset(id,0,sizeof(id));
            tot = 0,sum = 0;
            while(!s.empty()) s.pop();
            memset(all,0,sizeof(all));
            for(int i = 1; i <= n; i++)
            {
                if(!dfn[i])
                {
                    tarjan(i,-1);
                }
            }
            //cout<<"sum = "<<sum<<endl;
            int vis[maxn];
            memset(vis,0,sizeof(vis));
            int du[maxn];
            memset(du,0,sizeof(du));
            /*for(int i = 1;i <= sum;i++)
            {
                cout<<"all = "<<all[i]<<endl;
            }*/
            for(int u = 1; u <= n; u++)
            {
                for(int j = head[u]; j != -1; j = edge[j].nxt)
                {
                    int v = edge[j].to;
                    if(id[u] != id[v])
                    {
                        du[id[u]]++;
                    }
                }
            }
            int sub = 0,last = 0;
            for(int i = 1; i <= sum; i++)
            {
                if(du[i] == 0)
                {
                    sub++;
                    last = i;
                }
            }
            if(sub != 1) puts("0");
            else printf("%d
    ",all[last]);
        }
        return 0;
    }
  • 相关阅读:
    当import的模块内容发生变化时,对此模块进行重新加载(刷新)
    使用python的ctypes库实现内存的动态申请和释放
    【转载】实现博客园图片的可放大功能
    使用tqdm实现下载文件进度条
    pytest参数化的两种方式
    Jmeter之Bean shell使用-常用内置变量
    JMeter之Ramp-up Period(in seconds)说明
    Jmeter性能测试基础
    接口测试基础
    JMeter做http接口功能测试
  • 原文地址:https://www.cnblogs.com/jifahu/p/5506565.html
Copyright © 2020-2023  润新知