• Papa的朋友圈(原POJ 2186)Tarjan


    题目描述

    Papa朋友圈里的每一个人都梦想成为朋友圈里的网红。被所有人喜欢的人就是一个网红。Papa所有的朋友都是自恋狂,每个人总是喜欢自己的。人与人之间的“喜欢”是可以传递的——如果A喜

    欢B,B喜欢C,那么A也喜欢C。Papa的朋友圈里共有N 个人,给定一些这些人之间的喜欢关系,请你算出有多少个人可以当网红。

     

    输入格式: 
    第一行:两个用空格分开的整数:N和M

    第二行到第M + 1行:每行两个用空格分开的整数:A和B,表示A喜欢B

    输出格式: 
    第一行:单独一个整数,表示朋友圈网红的数量

     

    输入样例: 
    3 3 
    1 2 
    2 1 
    2 3 
    输出样例: 

    说明

    只有 3 号可以做网红

    【数据范围】

    10%的数据N<=20, M<=50

    30%的数据N<=1000,M<=20000

    70%的数据N<=5000,M<=50000

    100%的数据N<=10000,M<=50000


     虽然是道Tarjan裸题,但没有学长指导确实自己做不出来

    解析:

    这道题我们用一个动态数组(vector)来储存A 喜欢 B,相当于建一条 A 指向 B 的单向边

    如图

    本来的关系应是这样:

    Tarjan后:

    我们用一个 degree[] 储存出口,在两点不为强联通分量时才存在出口,因此我们把出口的degree保持为 0,其余则改变为true 

    讲道理出口有且仅有一个

    如果存在两个出口,那答案一定为0 —— 一定有两人互不喜欢,就不满足条件啦

    MY:

    #include<stdio.h>
    #include<algorithm>
    #include<stack>
    #include<vector>
    using namespace std;
    const int MX=10001;
    int n,m,k,cnt,dfn[MX],low[MX],belong[MX],degree[MX];
    bool vis[MX];
    stack<int> stk;
    vector<int> mp[MX];
    
    void Tarjan(int x)
    {
        dfn[x]=low[x]=++k;
        vis[x]=1;
        stk.push(x);
        for(int j=0;j<mp[x].size();++j)
        {
            int next=mp[x][j];
            if(!dfn[next])
            {
                Tarjan(next);
                low[x]=min(low[x],low[next]);
            }
            else {
                low[x]=min(low[x],dfn[next]);
            }
        }
        if(dfn[x] == low[x])
        {
            int top;
            cnt++;
            do
            {
                top=stk.top();
                stk.pop();
                belong[top]=cnt;
                
            }while(top!=x);
        }
        
    }
    
    void sol()
    {
        int ans=0,sum=0,index;
        for(int i=1;i<=n;++i)
        {
            for(int j=0;j<mp[i].size();++j)
            {
                if(belong[i] != belong[mp[i][j]])
                degree[belong[i]]++;
            }
        }
        for(int i=1;i<=cnt;++i)
        {
            if(!degree[i]) 
            sum++,index=i;
        }
        if(sum>1) {
            printf("0");
        }
        else {
            for(int i=1;i<=n;++i)
            {
                if(belong[i] == index) {
                    ans++;
                }
            }
            printf("%d",ans);
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;++i)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            mp[a].push_back(b);
        }
        for(int i=1;i<=n;++i)
        {
            if(!dfn[i])
                Tarjan(i);
        }
        sol();
        return 0;
    }

    学长滴:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<stdlib.h>
    #include<vector>
    #include<stack>
    using namespace std;
    #define N 10005
    stack<int> sta;
    vector<int> mp[N];
    int dfn[N],low[N],vis[N],num[N],degree[N];
    int n,m,cnt,id,ans;
     
    void init(){
        cnt=0;
        id=0;
        ans=0;
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(vis,0,sizeof(vis));
        memset(num,0,sizeof(num));
        memset(degree,0,sizeof(degree));
        while(!sta.empty())
            sta.pop();
        for(int i=1;i<=n;i++)
            mp[i].clear();
    }
     
    void tarjan(int x){
        dfn[x]=low[x]=++id;
        sta.push(x);
        vis[x]=1;
        for(int i=0;i<mp[x].size();i++){
            int t=mp[x][i];
            if(!dfn[t]) {
                tarjan(t);
                low[x]=min(low[x],low[t]);
            }
            else if(vis[t]) low[x]=min(low[x],dfn[t]);
        }
     
        if(dfn[x]==low[x]){
            int tp;
            cnt++;
            do{
                tp=sta.top();
                vis[tp]=0;
                num[tp]=cnt;
                sta.pop();
            }while(tp!=x);
        }
    }
     
    void solve(){
        int sum=0,index;
        for(int i=1;i<=n;i++){
            for(int j=0;j<mp[i].size();j++){
                if(num[i]!=num[mp[i][j]])
                    degree[num[i]]++;
            }
        }
     
        for(int i=1;i<=cnt;i++){
            if(!degree[i])
                sum++,index=i;
        }
    
        if(sum>1) cout<<"0"<<endl;
        else 
        {
            for(int i=1;i<=n;i++)
                if(num[i]==index)
                    ans++;
            cout<<ans<<endl;
        }
    }
     
     
    int main(){
        while(cin>>n>>m){
            init();
            for(int i=0;i<m;i++){
                int a,b;
                cin>>a>>b;
                mp[a].push_back(b);
            }
            for(int i=1;i<=n;i++)
                if(!dfn[i])
                    tarjan(i);
            solve();
        }
    }
    /*
    3 4
    1 2
    2 1
    2 3
    3 2
    */
    从0到1很难,但从1到100很容易
  • 相关阅读:
    MVC ORM 架构
    Kubernetes 第八章 Pod 控制器
    Kubernetes 第七章 Configure Liveness and Readiness Probes
    Kubernetes 第六章 pod 资源对象
    Kubernetes 第五章 YAML
    Kubernetes 核心组件
    Kubernetes 架构原理
    Kubernetes 第四章 kubectl
    Kubernetes 第三章 kubeadm
    yum 配置及yum 源配置
  • 原文地址:https://www.cnblogs.com/qseer/p/9389354.html
Copyright © 2020-2023  润新知