zoukankan      html  css  js  c++  java
  • PKU2186 Popular Cows 受欢迎的牛

    Description

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

    Input

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

    Output

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

    Sample Input

    3 3
    1 2
    2 1
    2 3

    Sample Output

    1




    这是一道关于强连通的题,首先建好强连通分量;
    再统计每个强连通的出度,如果有一个强连通出度为0;
    则,这个强连通没有可以到达其它强连通的有向边;
    也同时说明,这个强连通内的牛只互相喜欢,没有喜欢其它的牛;
    但是不能有多个强连通分量出度为0;要保证它是被所有的牛喜欢的;
    这样就算出,唯一出度为0的强连通分量里有多少头牛就可以了;

    附上代码
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline ll read()
    {
        ll a=0,f=1; char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
        while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
        return a*f;
    }
    ll n,m,ans,sum,s,top,num;
    ll head[100001],low[50001],dfn[50001];
    ll f[50001],aa[50001],cd[50001],anss[50001];
    struct sbbbbbbb
    {
        ll to,stb;//to为这条边到达的点,stb为上条边的编号 
    }a[100001];
    inline void insert(ll x,ll y)
    {
        s++;
        a[s].to=y;
        a[s].stb=head[x];
        head[x]=s;
    }//前向星连边 
    inline void dfs(ll x)
    {
        num++;
        dfn[x]=low[x]=num;
        top++;
        aa[top]=x;
        for(ll i=head[x];i;i=a[i].stb)//基础的遍历求low,和dfn的值 
        {
            ll xx=a[i].to;
            if(!dfn[xx])
            {
                dfs(xx);
                low[x]=min(low[x],low[xx]);
            }
            else if(!f[xx])
                low[x]=min(low[x],dfn[xx]);
        }
        if(low[x]==dfn[x])//如果可以通过返祖边回答父节点,
                          //那么这些点都属于一个强连通分量 
        {
            sum++;
            f[x]=sum;//标记属于哪个强连通 
            while(aa[top]!=x)
            {
                f[aa[top]]=sum;//标记属于哪个强连通 
                anss[sum]++;//计算这个强连通分量里有多少个点 
                top--;
            }
            anss[sum]++;
            top--;
        }
    }
    int main()
    {
        n=read();m=read();
        for(ll i=1;i<=m;i++)
        {
            ll x,y;
            x=read();y=read();
            insert(x,y);//连边 
        }
        for(ll i=1;i<=n;i++)
        if(!dfn[i])
            dfs(i);
        for(ll i=1;i<=n;i++)
        for(ll j=head[i];j;j=a[j].stb)
        if(f[i]!=f[a[j].to])//如果他们不是在一个强连通分量,
                           //并且可以由f[i]到达f[a[j].to] 
            cd[f[i]]++;//统计f[i]这个强连通的出度 
        for(ll i=1;i<=sum;i++)
        if(!cd[i])//枚举,看是否有出度为0的强连通 
        {
            if(ans==0)
                ans=anss[i];
            else//有多个出度为0,则没有答案 
            {
                printf("0");
                return 0;
            }
        }
        printf("%lld",ans);
    }

    下面纯属搞笑,可以不理会:

    黄牛模板:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline ll read()
    {
        ll a=0,f=1; char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
        while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
        return a*f;
    }
    ll n,m,ans,sum,s,top,num;
    ll head[100001],low[50001],dfn[50001];
    ll f[50001],aa[50001],cd[50001],anss[50001];
    struct sbbbbbbb
    {
        ll to,stb; 
    }a[100001];
    inline void insert(ll x,ll y)
    {
        s++;
        a[s].to=y;
        a[s].stb=head[x];
        head[x]=s;
    } 
    inline void dfs(ll x)
    {
        num++;
        dfn[x]=low[x]=num;
        top++;
        aa[top]=x;
        for(ll i=head[x];i;i=a[i].stb) 
        {
            ll xx=a[i].to;
            if(!dfn[xx])
            {
                dfs(xx);
                low[x]=min(low[x],low[xx]);
            }
            else if(!f[xx])
                low[x]=min(low[x],dfn[xx]);
        }
        if(low[x]==dfn[x])  
        {
            sum++;
            f[x]=sum; 
            while(aa[top]!=x)
            {
                f[aa[top]]=sum; 
                anss[sum]++; 
                top--;
            }
            anss[sum]++;
            top--;
        }
    }
    int main()
    {
        n=read();m=read();
        for(ll i=1;i<=m;i++)
        {
            ll x,y;
            x=read();y=read();
            insert(x,y); 
        }//输入牛的编号 
        for(ll i=1;i<=n;i++)
        if(!dfn[i])
            dfs(i);//找谁是最受欢迎的牛 
        printf("最 受 欢 迎 的 牛 是 黄 牛
    我 是 黄 牛 沃 泰 牛");
    }

    只要将黄牛模板交到入门oj的4916

    就会AC

  • 相关阅读:
    skymvc文件上传支持多文件上传
    skymvc网站测试之mysql数据生成
    欢迎使用skymvc框架,简单易用的php框架
    模式识别与机器学习(第四章学习记录和心得)
    python实现MICD分类器
    python实现MED分类器
    模式识别与机器学习(第一至三章学习记录和心得)
    软工实践个人总结
    第09组 每周小结 (3/3)
    第09组 每周小结 (2/3)
  • 原文地址:https://www.cnblogs.com/wzx-RS-STHN/p/12936800.html
Copyright © 2011-2022 走看看