1 条题解

  • 0
    @ 2025-8-24 21:41:53

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 「QQ红包」
    **

    搬运于2025-08-24 21:41:53,当前版本为作者最后更新于2017-07-10 12:56:50,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    tarjan的模板题(嗯可以看lrj的书

    -第一问:至少要给多少个学校软件,才能保证所有学校都有软件用,也就是求缩点后入度为0的点的个数(因为入度为0的话没有其他学校能传软件给它)

    -第二问:使缩点后所有学校的入度和出度都大于0(这样就可以给任意学校软件,然后所有学校都能用上软件

    如果是一个强连通图需要特判。

    /*
    ID: ylx14271
    PROG: schlnet
    LANG: C++
    */
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<stack>
    #include<cstdio>
    using namespace std;
    int read()
    {
        char ch=getchar();
        int x=0;
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); 
        return x;
    }
    int s[20100],top;
    int low[21000];//存能搜到的最早的点 
    int pre[21000];//存自己的时间 
    int dfs_clock; 
    struct node
    {
        int x,y,d;
    } a[4000000];
    int po[21000],m;
    int n,x1;
    int scc[21000],id;
    int c[21000];//出度 
    int r[21000];//入度 
    
    void dfs(int u)
    {
        top++;
        s[top]=u;
        low[u]=++dfs_clock; //存自己的时间和 
        pre[u]=dfs_clock; 
        for (int i=po[u];i!=0;i=a[i].d)
        {
            int v=a[i].y;//提出点 
            if (pre[v]==0)//没有扫过 
            {
                dfs(v);//扫一遍 
                low[u]=min(low[u],low[v]);//更新 
            } else
            if (scc[v]==0)//如果在别的联通块就不管了 
            {
                low[u]=min(low[u],pre[v]);
            }
        }
        int k; 
        if (pre[u]==low[u])//自己是自己的祖先(也就是扫不到时间更早的点了 
        {
            id++;
            while (1)
            {
                k=s[top];top--;
                scc[k]=id;
                if (k==u) break;
            }
        }
    }
    int main()
    {
        freopen("schlnet.in","r",stdin);
        freopen("schlnet.out","w",stdout);
        n=read();
        for (int i=1;i<=n;i++)
        {
            x1=read();
            while (x1!=0)
            {
                m++;
                a[m].x=i;
                a[m].y=x1;
                a[m].d=po[a[m].x];
                po[a[m].x]=m;
                x1=read();
            }
        }//读入 
        for (int j=1;j<=n;j++)
        {//因为并不一定是个连通图,so 
            if (pre[j]==0) dfs(j);
        }
        for (int i=1;i<=m;i++)
        {
            if (scc[a[i].x]!=scc[a[i].y])//自己图内不管 
            {
                c[scc[a[i].x]]++;//x的出度+1 
                r[scc[a[i].y]]++;//y的入度+1 
            }
        } 
        int ans1=0;
        int ans2=0;
        for (int i=1;i<=id;i++)//统计出度入度为0的点的出现次数 
        {
            if (r[i]==0) ans1++;
            if (c[i]==0) ans2++;
        }
        ans2=max(ans2,ans1);//第二问,所有点要出度不为0而且入度不为0 
        if (id==1) ans1=1,ans2=0;//嗯要特判 
        printf("%d\n%d\n",ans1,ans2);
        return 0;
    }
    
    • 1

    校园网络【[USACO] Network of Schools加强版】

    信息

    ID
    1888
    时间
    1000ms
    内存
    128MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者