zoukankan      html  css  js  c++  java
  • bzoj1051受欢迎的牛(Tarjan)

    1051: [HAOI2006]受欢迎的牛

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 4776  Solved: 2542

    Description

      每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
    种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
    牛被所有的牛认为是受欢迎的。

    Input

      第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可
    能出现多个A,B)

    Output

      一个数,即有多少头牛被所有的牛认为是受欢迎的。

    Sample Input

    3 3
    1 2
    2 1
    2 3

    Sample Output

    1

    HINT

     

    100%的数据N<=10000,M<=50000
    /*这是一个缩点Tarjan求环的裸题 */ 
    #include<iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int Maxn = 10005;
    const int Maxm = 100005;
    struct node
    {
        int to,next;
    } edge[Maxm];
    int n,m,head[Maxn],dfn[Maxn],low[Maxn],stack1[Maxn],num[Maxn],du[Maxn],vis[Maxn],cnt,tt,top,cut;
    
    void init()
    {
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(head,-1,sizeof(head));
        memset(vis,0,sizeof(vis));
        memset(num,0,sizeof(num));
        memset(du,0,sizeof(du));
    }
    
    void addedge(int u,int v)
    {
        edge[cnt].to=v;
        edge[cnt].next=head[u];
        head[u]=cnt;
        cnt++;
    }
    
    void Tarjan(int u,int fa)
    {
        dfn[u]=tt;
        low[u]=tt;
        tt++;
        vis[u]=1;
        stack1[top]=u;
        top++;
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].to;
            if(!vis[v])
            {
                Tarjan(v,u);
                low[u]=min(low[u],low[v]);
            }
            else if(vis[v])
            {
                low[u]=min(low[u],dfn[v]);
            }
        }
        if(low[u]==dfn[u])
        {
            cut++;
            while(top>0&&stack1[top]!=u)
            {
                top--;
                vis[stack1[top]]=2;
                num[stack1[top]]=cut;
            }
        }
    }
    
    int main()
    {
        int u,v;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            init();
            for(int i=0; i<m; i++)
            {
                scanf("%d%d",&u,&v);
                addedge(u,v);
            }
            for(int i=1; i<=n; i++)
            {
                if(!vis[i])
                {
                    Tarjan(i,0);
                }
            }
            for(int i=1; i<=n; i++)
            {
                for(int j=head[i]; j!=-1; j=edge[j].next)
                {
                    if(num[i]!=num[edge[j].to])
                    {
                        du[num[i]]++;
                    }
                }
            }
            int sum=0,x;
            for(int i=1; i<=cut; i++)
            {
                if(!du[i])
                {
                    sum++;
                    x=i;
                }
            }
            if(sum==1)
            {
                sum=0;
                for(int i=1; i<=n; i++)
                {
                    if(num[i]==x)
                    {
                        sum++;
                    }
                }
                printf("%d
    ",sum);
            }
        }
        return 0;
    }
    心若向阳,无谓悲伤
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=10005,M=50005;
    int n=0,m=0;
    int head[N],to[M],next[M],edge=0;
    int dfn[N],inS[N],idx=1,low[N];
    int stk[N],top=0;
    int comp[N],n2=0,cnt[N];
    int in[N];
    int head2[N],to2[M],next2[M],edge2=0;
    int q[N*233],front=0,back=0,vis[N];
    inline void addEdge(int u,int v) {
        to[edge]=v,next[edge]=head[u],head[u]=edge++;
    }
    void tarjan(int x) {
        dfn[x]=low[x]=idx++;
        stk[top++]=x;
        inS[x]=1;
        for (int e=head[x];~e;e=next[e]) {
            int& v=to[e];
            if (!dfn[v]) {
                tarjan(v);
                low[x]=min(low[x],low[v]);
            } else if (inS[x]) 
                low[x]=min(low[x],dfn[v]);
        }
        if (dfn[x]==low[x]) {
            ++n2;
            int u=0;
            do {
                u=stk[--top];
                comp[u]=n2;
                inS[u]=0;
                ++cnt[n2];
            } while (u!=x);
        }
    }
    inline void addEdge2(int u,int v) {
        ++in[v];
        to2[edge2]=v,next2[edge2]=head2[u],head2[u]=edge2++;
    }
    inline void build() {
        for (int i=1;i<=n;++i)
            for (int e=head[i];~e;e=next[e]) {
                int &u=comp[i],&v=comp[to[e]];
                if (u!=v)
                    addEdge2(v,u);
            }
    }
    inline int bfs(int s) {
        front=back=0;
        memset(vis,0,sizeof(vis));
        q[back++]=s;
        vis[s]=1;
        while (front<back) {
            int x=q[front++];
            for (int e=head2[x];~e;e=next2[e]) {
                int& v=to2[e];
                if (!vis[v]) {
                    q[back++]=v;
                    vis[v]=1;
                }
            }
        }
        for (int i=1;i<=n2;++i)
            if (!vis[i])
                return 0;
        return 1;
    }
    int main(void) {
        memset(head,-1,sizeof(head));
        scanf("%d %d",&n,&m);
        while (m--) {
            int u=0,v=0;
            scanf("%d %d",&u,&v);
            addEdge(u,v);
        }        
        for (int i=1;i<=n;++i)
            if (!dfn[i])
                tarjan(i);
        //建缩点以后的反图 就所有入度为0的点bfs
         memset(head2,-1,sizeof(head2));
         build();
         int ans=0;
         for (int i=1;i<=n2;++i)
             if (!in[i])
                 if (bfs(i))
                     ans+=cnt[i];
        printf("%d
    ",ans);
        return 0;
    } 
    上个代码在洛谷不过,求大神指点
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    angular 实现全选、反选、个别选择的实现
    idea下git版本回退
    统一设置滚动条样式
    vue小知识点
    Java面试题之Oracle 支持哪三种事务隔离级别
    Java面试题之hashmap中用什么hash算法解决碰撞的?
    Java面试题之Integer.valueOf(String s);采用了什么设计模式
    TCP面试题之为什么会有TIME_WAIT状态
    Java面试题之如何防止重复下单问题?
    Java面试题之在多线程情况下,单例模式中懒汉和饿汉会有什么问题呢?
  • 原文地址:https://www.cnblogs.com/L-Memory/p/6159720.html
Copyright © 2011-2022 走看看