• 洛谷P2341 受欢迎的牛 Tarjan缩点


    题目链接:https://www.luogu.org/problem/P2341

    题意:A喜欢B,B喜欢C,那么A就喜欢C,每个人都必定喜欢自己,求问被所有人喜欢的人有多少个

    输入格式:n,m分别是人总数和喜欢关系的数目,接下来m行每行两个数字a,b代表a喜欢b

    分析:输入格式方面很容易想到可以转化成图论题来做,在图上,A喜欢B就代表A可达B,强连通分量里面所有点是互相可达的,而强连通分量a只要有一个点可达强连通分量b,那么a中所有点都可达b,我们便利用Tarjan算法算出强连通分量并且记录每个强连通分量里点的个数,然后进行缩点。缩点后我们继续观察,发现如果出度为0的点只有一个,那么这肯定是个连通图,并且其他所有点可以达到该点,而该点无法到达其他点,那么这个点(缩点后的强连通分量)内点的个数就是答案,而若有两个以上的点出度为0,该图则不是联通图,答案为0.

    直接套Tarjan算法缩点模板,记录数目并最后记录每个点出度即可即可。

    #include<bits/stdc++.h>
    #define maxn 10001
    using namespace std;
    vector<int>G[maxn];
    stack<int>s;
    int n,m;
    int dfn[maxn],vis[maxn],low[maxn],color[maxn],num[maxn],colornum=0,res[maxn],cnt;
    //num记录每个颜色下点的数目,res记录每个点的出度 
    void paint(int x)
    {
        s.pop();
        color[x]=colornum;
        num[colornum]++;
        vis[x]=false;
    }
    void tarjan(int x)
    {
        dfn[x]=low[x]=++cnt;
        s.push(x);
        vis[x]=true;
        for(int i=0;i<G[x].size();i++)
        {
            int q=G[x][i];
            if (!dfn[q])
            {
                tarjan(q);
                low[x]=min(low[x],low[q]);
            }
            else if (vis[q]) low[x]=min(low[x],dfn[q]);
        }
        if (low[x]==dfn[x])
        {
            colornum++;
            while(s.top()!=x)
            {
                int t=s.top();
                paint(t);
            }
            paint(x);
        }
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=m;i++)
        {
            int u,v;
            cin>>u>>v;
            G[u].push_back(v);
        }
        for(int i=1;i<=n;i++)
        {
            if (!dfn[i]) tarjan(i);
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<G[i].size();j++){
                if(color[i]!=color[G[i][j]]){
                    res[color[i]]++;
                }
            }
        }
        for(int i=1;i<=colornum;i++){
            if(ans==0&&res[i]==0){
                ans=num[i];
            }
            else if(res[i]==0){
                ans=0;break;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    HDU 1713 相遇周期 (最小公倍数)
    HDU 1270 小希的数表 (暴力枚举+数学)
    HDU 1052 Tian Ji -- The Horse Racing (贪心)
    CodeForces 732D Exams (二分)
    CodeForces 732C Sanatorium (if-else)
    CodeForces 732B Cormen — The Best Friend Of a Man (贪心)
    CodeForces 732A Buy a Shovel (水题)
    CodeForces 743C Vladik and fractions (数论)
    Node基础
    正向代理与反向代理
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/11313561.html
Copyright © 2020-2023  润新知