• P2746 [USACO5.3]校园网Network of Schools


    传送门

    把所有学校的关系构成一个图,显然一个强联通分量的所有学校只要有一个有新软件,其他学校也都会有

    考虑缩点,发现入度为 0 的块一定要给,因为没有其他人给它

    入度不为 0 的块一定有其他人给,我们只要给 能给它的块 提供软件就可以了

    所以就是入度为 0 的块一定给,不为 0 的块一定不用给

    子任务A就是求出入度为 0 的块的数量

    然后考虑子任务B

    显然出度为 0 的块一定要连边出去,入度为 0 的块也一定要有边连过来

    所以出度为 0 的块连给谁呢,当然给入度为 0 的块

    所以就是求 出度为 0 的块数量 和 入度为 0 的块的数量的较大值

    当然别忘了特判整个图本身就是联通块的情况

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=1007;
    int n;
    int fir[N],from[N<<1],to[N<<1],cntt;
    inline void add(int &a,int &b)
    {
        from[++cntt]=fir[a];
        fir[a]=cntt; to[cntt]=b;
    }
    
    //Tarjan模板
    int dfs_clock,dfn[N],low[N],st[N],Top;
    int bel[N],tot;//存每个点属于哪个块
    void Tarjan(int x)
    {
        dfn[x]=low[x]=++dfs_clock; st[++Top]=x;
        for(int i=fir[x];i;i=from[i])
        {
            int &v=to[i];
            if(!dfn[v]) Tarjan(v),low[x]=min(low[x],low[v]);
            else if(!bel[v]) low[x]=min(low[x],dfn[v]);
        }
        if(low[x]==dfn[x])
        {
            tot++;
            while(st[Top]!=x) { bel[st[Top]]=tot; Top--; }
            bel[x]=tot; Top--;
        }
    }
    int in[N],out[N],ans1,ans2;//入度,出度,入度为0的数量和出度为0的数量
    inline void build()//计算in,ouw,ans1,ans2
    {
        for(int i=1;i<=n;i++)
            for(int j=fir[i];j;j=from[j])
            {
                int &t=to[j];
                if(bel[i]==bel[t]) continue;//同块内不考虑
                out[bel[i]]++; in[bel[t]]++;
            }
        for(int i=1;i<=tot;i++)
        {
            if(!in[i]) ans1++;
            if(!out[i]) ans2++;
        }
    }
    
    int main()
    {
        int a;
        n=read();
        for(int i=1;i<=n;i++)
        {
            a=read();
            while(a) add(i,a),a=read();
        }
        for(int i=1;i<=n;i++) if(!bel[i]) Tarjan(i);
        build();
        if(tot==1) printf("%d
    %d",1,0);//特判
        else printf("%d
    %d",ans1,max(ans1,ans2));
        return 0;
    }
  • 相关阅读:
    iOS关于本地推送
    [转]iOS8 自动调整UITableView和UICollectionView布局
    [转]在Storyboard中使用自定义的segue类型
    iOS 判断来电状态CTCallCenter代码块不执行问题的解决
    centos 用docker搭建elasticsearch 集群
    element-ui 使用upload上传文件并解决跨域问题
    mysql 常见关键字大全和引擎的差异
    Guava---文件操作Files
    springboot这个redies 查看内存信息
    人生也要动态规划
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9854616.html
Copyright © 2020-2023  润新知