usaco Network of Schools

强连通分量的求解,虽说第一眼一看数据量就知道能用Floyd写,但是谁让我太渣呢,还是别偷懒了。熟悉下tarjan。

 
/*
ID: modengd1
PROG: schlnet
LANG: C++
*/
#include <iostream>
#include <stdio.h>
#include <vector>
#include <stack>
#include <memory.h>
using namespace std;
bool vis[101];
bool insatck[101];
vector<int> G[101];
int N;
int dfn[101];
int low[101];
stack<int> ST;
int ind;
int colored[101];
int color;
int newG[101][101];
void tarjan(int u)
{
    vis[u]=true;
    low[u]=dfn[u]=++ind;
    ST.push(u);
    insatck[u]=true;
    for(int i=0;i<G[u].size();i++)
    {
        if(!vis[G[u][i]])
        {
            tarjan(G[u][i]);
            low[u]=min(low[G[u][i]],low[u]);
        }
        else if(insatck[G[u][i]])
        {
            low[u]=min(low[u],dfn[G[u][i]]);
        }
    }
    if(low[u]==dfn[u])//同一个联通分量中的点染成一个颜色
    {
        color++;
        while(ST.top()!=u)
        {
            colored[ST.top()]=color;
            insatck[ST.top()]=false;
            ST.pop();
        }
        colored[ST.top()]=color;
        insatck[ST.top()]=false;
        ST.pop();
    }
}
void buildnew()
{
    memset(newG,false,sizeof(newG));
    for(int i=1;i<=N;i++)
    {
        for(int j=0;j<G[i].size();j++)
        {
            if(colored[i]!=colored[G[i][j]])
            newG[colored[i]][colored[G[i][j]]]=true;
        }
    }
    int cterO[101],cterI[101];
    memset(cterO,0,sizeof(cterO));
    memset(cterI,0,sizeof(cterI));
    for(int i=1;i<=color;i++)
    {
        for(int j=1;j<=color;j++)
        {
            if(newG[i][j])
            {
                cterO[i]++;
                cterI[j]++;
            }
        }
    }
    int ans0=0,ans1=0;
    for(int i=1;i<=color;i++)
    {
        if(cterI[i]==0)//入度为零的点的个数
            ans0++;
        if(cterO[i]==0)//出度为零的点的个数
            ans1++;
    }
    if(color==1)
    {
        cout<<1<<endl<<0<<endl;
    }
    else
    {
        cout<<ans0<<endl<<max(ans0,ans1)<<endl;
    }
}
int main()
{
    freopen("schlnet.in","r",stdin);
    freopen("schlnet.out","w",stdout);
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
    {
        int v;
        while(scanf("%d",&v)&&v!=0)
        {
            G[i].push_back(v);
        }
    }
    ind=0;
    color=0;
    memset(colored,0,sizeof(color));
    for(int i=1;i<=N;i++)
    {
        if(colored[i]==0)
            tarjan(i);
    }
    buildnew();
    return 0;
}

  

  

posted on 2015-10-08 00:58  insaneman  阅读(140)  评论(0编辑  收藏  举报

导航