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

 

>>> 去看 极值 度数   rd==0 cd==0 连起来就是环  -> max(rd==0 sum, cd==0 sum)

>>> 每一对点 只能算出 缩点 rd cd ==0 的情况,

#include<cstdio>
#include<bits/stdc++.h>
using namespace std;

const int N=105,M=2e4+5;

stack<int> st;
int n;
int head[N],tot=0,dfn[N],low[N],num=0,co[N],col=0;

struct EDGE
{
    int to,nxt;
} e[M];

void add(int u,int v)
{
    e[++tot].to=v;
    e[tot].nxt=head[u];
    head[u]=tot;
}


void Tarjan(int u)
{
    dfn[u]=low[u]=++num;
    st.push(u);
    
    for(int i=head[u];i;i=e[i].nxt)
    {
        int v=e[i].to;
        
        if(dfn[v]==0)
        {
            Tarjan(v);
            low[u]=min(low[u],low[v]);//
        }
        else if(co[v]==0)
        {
            low[u]=min(low[u],dfn[v]);//
        }
    }
        if(low[u]==dfn[u])//
        {
            co[u]=++col;
            
            while(st.top()!=u)
            {
                co[st.top()]=col;
                st.pop();
            }
            st.pop();
        }
    
}

int ans1,ans2,vis[N][N]={0};

void count()
{

    for(int i=1;i<=n;i++)
    {
        for(int j=head[i];j;j=e[j].nxt)
        {
            if(co[e[j].to]!=co[i])//&&vis[i][e[j].to]==0)
            {
                //vis[i][e[j].to]=1;
                vis[0][co[e[j].to]]++;// rd
                vis[co[i]][0]++;//cd
            }
        }
    }
}


int main()
{
    cin>>n;
    
    for(int i=1;i<=n;i++) 
    {
        int x;
        
        while(scanf("%d",&x)&&x)  add(i,x);
    }
    
    for(int i=1;i<=n;i++)
        if(dfn[i]==0)
            Tarjan(i);
      
     
    count();
    
    for(int i=1;i<=col;i++)// if col==1 -> 1
    {
        ans1+=(vis[0][i]==0);
        ans2+=(vis[i][0]==0);
    }
    
    cout<<ans1<<endl<<((col==1)? 0:max(ans1,ans2))<<endl;
    
    return 0;
}
View Code

 

 
posted @ 2023-08-07 21:51  JMXZ  阅读(13)  评论(0)    收藏  举报