现在的位置: 首页 > 综合 > 正文

[poj 2186]Popular Cows[Tarjan强连通分量]

2018年03月17日 ⁄ 综合 ⁄ 共 1092字 ⁄ 字号 评论关闭

题意:

有一群牛, a会认为b很帅, 且这种认为是传递的. 问有多少头牛被其他所有牛认为很帅~

思路:

关键就是分析出缩点之后的有向树只能有一个叶子节点(出度为0).

做法就是Tarjan之后缩点统计出度.

#include <cstdio>
#include <cstring>
#include <stack>
#include <algorithm>
using namespace std;
const int MAXN = 10005;
const int MAXE = 50005;
struct pool
{
    int v,pre;
}p[MAXE];
int num,head[MAXN];
int dfn[MAXN],low[MAXN],id[MAXN],dag[MAXN];
bool vis[MAXN];
int size,Index,n,m;
stack<int> s;
void add(int u, int v)
{
    p[++num].v = v;
    p[num].pre = head[u];
    head[u] = num;
}

void Tarjan(int u)
{
    low[u] = dfn[u] = ++Index;
    vis[u] = true;
    s.push(u);
    for(int tmp = head[u],k;k = p[tmp].v,tmp;tmp = p[tmp].pre)
    {
        if(!dfn[k])
        {
            Tarjan(k);
            low[u] = min(low[u],low[k]);
        }
        else if(vis[k])
            low[u] = min(low[u],low[k]);
    }
    if(dfn[u]==low[u])
    {
        size++;
        int k;
        do
        {
            k = s.top();s.pop();
            vis[k] = false;
            id[k] = size;
        }while(k!=u);
    }
}

void shrink()
{
    for(int i=1;i<=n;i++)
        for(int tmp = head[i],k;k = p[tmp].v,tmp;tmp = p[tmp].pre)
            if(id[i]!=id[k])
                dag[id[i]]++;//缩点
}

int main()
{
    scanf("%d %d",&n,&m);
    for(int i=0,u,v;i<m;i++)
    {
        scanf("%d %d",&u,&v);
        add(u, v);
    }
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
            Tarjan(i);
    }
    shrink();
    int ans = 0,tmp;
    for(int i=1;i<=n;i++)
    {
        if(!dag[id[i]])
        {
            if(!ans)    tmp = id[i];
            else if(tmp!=id[i])
            {
                ans = 0;
                break;
            }
            ans++;
        }
    }
    printf("%d\n",ans);
}

抱歉!评论已关闭.