[USACO5.3]校园网Network of Schools

[USACO5.3]校园网Network of Schools

\(Tarjan\)板子+特判

不是很懂这个数据范围为什么是\(10^2\)害的我一直在想什么\(O(n^3)\)\(O(n^4)\)的算法…………结果似乎是个\(O(n^2)\)的……

\(Tarjan\)缩点;

  1. 子任务A:输出入度为零的点的个数;

  2. 子任务B:如果原图强联通输出0,否则输出\(max(入度0的点的个数,出度0的点的个数)\)

code:

#include<bits/stdc++.h>
using namespace std;
const int N=105,INF=0x3f3f3f3f;
inline int read()
{
    char c=getchar();int x=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        x=x*10+c-'0';
    return x;
}
int n;
vector<int> GG[N];
int DFN[N],ts,COL[N],LOW[N],colcnt,INDEG[N],OUDEG[N];
bool in[N];
stack <int> S;

void Tarjan(int u)
{
    LOW[u]=DFN[u]=++ts;
    S.push(u);
    in[u]=1;
    for(int i=0;i<GG[u].size();i++)
    {
        int v=GG[u][i];
        if(DFN[v]==0)
        {
            Tarjan(v);
            LOW[u]=min(LOW[u],LOW[v]);
        }
        else if(in[v])
        {
            LOW[u]=min(LOW[u],DFN[v]);
        }
    }
    if(DFN[u]==LOW[u])
    {
        ++colcnt;
        while(!S.empty())
        {
            int x=S.top();
            S.pop();
            in[x]=0;
            COL[x]=colcnt;
            if(x==u)break;
        }
    }
}

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        while(1)
        {
            int v=read();
            if(v==0)break;
            GG[i].push_back(v);
        }
    }
    for(int i=1;i<=n;i++)if(DFN[i]==0)Tarjan(i);
    
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<GG[i].size();j++)
        {
            int u=i,v=GG[i][j];
            if(COL[u]!=COL[v])
            {
                INDEG[COL[v]]++;
                OUDEG[COL[u]]++;
            }
        }
    }
    int res1=0,res2=0;
    for(int i=1;i<=colcnt;i++)
    {
        if(INDEG[i]==0)res1++;
        if(OUDEG[i]==0)res2++;
    }
    cout<<res1<<endl;
    if(colcnt==1)cout<<'0';
    else cout<<max(res1,res2);
    return 0;
}
posted @ 2019-11-12 09:08  miyasaka  阅读(126)  评论(0)    收藏  举报