IT民工
加油!

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1128

这道题是裸的强连通分量,之前没有写类似的题,所以敲的很辛苦。

/*Accepted    920 KB    32 ms    C++    2240 B    2012-07-28 16:54:39*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;

const int MAXN = 1 << 7;
struct edge
{
    int v, n;
} e[MAXN *MAXN];

int first[MAXN], es;

void addedge(int u, int v)
{
    e[es].v = v, e[es].n = first[u], first[u] = es++;
}

int n, m, tu, tv, ans;
int dfn[MAXN], low[MAXN], col[MAXN], stk[MAXN], ins[MAXN], ind, top, cols, tmp;
int indg[MAXN], outdg[MAXN], zeroin, zeroout;

void dfs(int u)
{
    dfn[u] = low[u] = ++ind;
    stk[++top] = u, ins[u] = 1;
    for(int i = first[u]; i != -1; i = e[i].n)
    {
        int v = e[i].v;
        if( dfn[v] == 0)
        {
            dfs(v);
            if(low[v] < low[u]) low[u] = low[v];
        }
        else if(ins[v])
        {
            if(dfn[v] < low[u]) low[u] = dfn[v];
        }
    }
    if(dfn[u] == low[u])
    {
        cols++;
        do
        {
            tmp = stk[top--];
            col[tmp] = cols;
            ins[tmp] = 0;
        }while(tmp != u);
    }
}


void tarjan( int n)
{
    memset(dfn, 0, sizeof dfn);
    memset(low, 0, sizeof low);
    memset(col, 0, sizeof col);
    memset(stk, 0, sizeof stk);
    memset(ins, 0, sizeof ins);
    ind = top = cols = 0;
    for(int i = 1; i <= n; i++)
    {
        if( dfn[i] == 0) dfs(i);
    }
    if(cols == 1)
    {
        ans = 0;
        return;
    }
    ans = zeroin = zeroout = 0;
    memset(indg, 0, sizeof indg);
    memset(outdg, 0, sizeof outdg);
    for(int u = 1; u <= n; u++)
    {
        for(int i = first[u]; i != -1; i = e[i].n)
        {
            int v = e[i].v;
            if(col[u] == col[v])continue;
            indg[col[v]]++;
            outdg[col[u]]++;
        }
    }
    for(int i = 1; i <= cols; i++)
    {
        if(indg[i] == 0)zeroin++;
        if(outdg[i] == 0)zeroout++;
    }
    ans = zeroin > zeroout ? zeroin : zeroout;
}

int main()
{
    while( scanf( "%d", &n) != EOF)
    {
        memset( first, -1, sizeof first);
        for( int i = 1; i <= n; i ++)
        {
            int a;
            while( true)
            {
                scanf( "%d", &a);
                if( a == 0) break;
                addedge( i, a);
            }
        }
        tarjan(n);
        printf( "%d\n", ans);
    }
    return 0;
}

 

 

posted on 2012-07-28 16:58  找回失去的  阅读(228)  评论(0)    收藏  举报