zoukankan      html  css  js  c++  java
  • USACO 2003 Fall Orange Popular Cows /// tarjan缩点 oj22833

    题目大意:

    n头牛,m个崇拜关系,并且崇拜具有传递性

    如果a崇拜b,b崇拜c,则a崇拜c

    求最后有几头牛被所有牛崇拜

    强连通分量内任意两点都能互达 所以只要强联通分量内有一点是 那么其它点也都会是

    按照崇拜关系 即a崇拜b就连一条a到b的边 tarjan求得所有强联通分量染色

    而把一个强联通分量缩成一个超级点后 整个图的崇拜关系就变成了一个 有向无环图

    此时被所有牛崇拜的牛就是 一个出度为0的超级点

    只要把所有边再走一遍就可以计算出度 同时计算每个超级点内有多少个点

    即从a出发到b的边 若a b的颜色相同说明是在同一个超级点内那么点数+1 颜色不同那么a的出度+1

    但当出现 多个出度为0的超级点 时 必然存在一个出度为0的超级点不被另一个出度为0的超级点崇拜

    那么就不满足被所有牛崇拜这个条件 此时答案为 0

    #include <stdio.h>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    using namespace std;
    
    const int N=10005;
    struct EDGE { int to, nt; }e[5*N];
    int head[N], tot;
    int dfn[N], low[N], ind;
    int col[N], id;
    bool vis[N];
    stack <int> s;
    
    int n, m, cnt[N], du[N];
    
    void init() {
        while(!s.empty()) s.pop();
        for(int i=0;i<=n;i++) {
            head[i]=dfn[i]=low[i]=col[i]=-1;
            vis[i]=cnt[i]=du[i]=0;
        }
        tot=ind=id=0;
    }
    void addE(int u,int v) {
        e[tot].to=v;
        e[tot].nt=head[u];
        head[u]=tot++;
    }
    
    void tarjan(int u) {
        dfn[u]=low[u]=ind++;
        s.push(u); vis[u]=1;
        for(int i=head[u];i!=-1;i=e[i].nt) {
            int v=e[i].to;
            if(dfn[v]==-1) {
                tarjan(v);
                low[u]=min(low[u],low[v]);
            } else {
                if(vis[v]) low[u]=min(low[u],low[v]);
            }
        }
        if(dfn[u]==low[u]) {
            col[u]=++id;
            vis[u]=0;
            while(s.top()!=u) {
                col[s.top()]=id;
                vis[s.top()]=0;
                s.pop();
            } s.pop();
        }
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&m)) {
            init();
            for(int i=1;i<=m;i++) {
                int u,v;
                scanf("%d%d",&u,&v);
                addE(u,v);
            }
            for(int i=1;i<=n;i++)
                if(dfn[i]==-1) tarjan(i);
            for(int i=1;i<=n;i++) {
                for(int j=head[i];j!=-1;j=e[j].nt)
                    if(col[e[j].to]!=col[i])
                        du[col[i]]++;// 计算出度
                cnt[col[i]]++;
            }
            int tmp=0, ans;
            for(int i=1;i<=id;i++)
                if(du[i]==0) tmp++, ans=cnt[i];
            if(tmp==1) printf("%d
    ",ans);
            else printf("0
    ");
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    ASP.NET Post方式提交
    MVC增加操作日志
    asp.net MVC 下拉多级联动及编辑
    redis基本数据类型之String
    关于idea下使用springinitializr创建项目时 初始化失败的解决
    Failed to read artifact descriptor for org.mybatis:mybatis:jar:2.2.1
    如何查看日志文件
    nginx 部署vue 以及同一端口下部署监听多个vue 项目
    JsonView 与JsonIgnore 使用
    vue 打包部署
  • 原文地址:https://www.cnblogs.com/zquzjx/p/10011531.html
Copyright © 2011-2022 走看看