zoukankan      html  css  js  c++  java
  • AcWing1174 受欢迎的牛(tarjan缩点)

    对于有向图问题,如果能转化成dag那么就会好做很多,因为这题如果是dag,那么只要只存在一格出度为0的,就是答案

    而强连通分量中的点都可以互达,所以进行tarjan缩点。

    tarjan缩点的原理,分为四个边,树边,前向边,后向边,横叉边

    dfn是时间戳,tarjan的栈中存的是祖先和已被遍历的并且能够走到当前节点祖先或者本身的点,以及本身。

    而low数组存的是只经过一条后向边或者横叉边可以走到的dfn最小的并且能够走到当前节点祖先或者本身的点,也就是栈中的点

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+10;
    int id[N];
    int h[N],ne[N],w[N],e[N],idx;
    stack<int> q;
    int scnt;
    int cnt[N];
    int times;
    int n,m;
    int dfn[N],low[N];
    int ins[N];
    int in[N];
    void tarjan(int u){
        dfn[u]=low[u]=++times;
        int i;
        q.push(u),ins[u]=1;
        for(i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(!dfn[j]){
                tarjan(j);
                low[u]=min(low[u],low[j]);
            }
            else if(ins[j]){
               low[u]=min(low[u],dfn[j]); 
            }
            
        }
        if(dfn[u]==low[u]){
            ++scnt;
            while(1){
                int t=q.top();
                q.pop();
                ins[t]=0;
                cnt[scnt]++;
                id[t]=scnt;
                if(t==u)
                break;
            }
        }
    }
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    int main(){
        cin>>n>>m;
        int i;
        memset(h,-1,sizeof h);
        for(i=1;i<=m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);
        }
        for(i=1;i<=n;i++){
            if(!dfn[i])
                tarjan(i);
        }
        int j;
        for(i=1;i<=n;i++){
            for(j=h[i];j!=-1;j=ne[j]){
                int k=e[j];
                if(id[i]!=id[k]){
                    in[id[i]]++;
                }
            }
        }
        int sum=0;
        int sign=0;
        for(i=1;i<=scnt;i++){
            if(!in[i]){
                sum+=cnt[i];
                sign++;
            }
            if(sign>1){
                sum=0;
                break;
            }
        }
        cout<<sum<<endl;
    }
    View Code
  • 相关阅读:
    JDBC面试问题
    Linux下如何实现MySQL数据库每天自动备份定时备份
    Linux下如何实现MySQL数据库每天自动备份定时备份
    Linux下如何实现MySQL数据库每天自动备份定时备份
    Random Forest And Extra Trees
    经济学十大原理
    JavaScript的执行机制
    单元测试
    JavaScript是如何工作的(一)
    阿里大数据竞赛season1 总结
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12934244.html
Copyright © 2011-2022 走看看