[HAOI2006][BZOJ1051] 受欢迎的牛

1051: [HAOI2006]受欢迎的牛

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2685  Solved: 1407
[Submit][Status][Discuss]

Description

每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。

Input

第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B)

Output

一个数,即有多少头牛被所有的牛认为是受欢迎的。

Sample Input

3 3
1 2
2 1
2 3

Sample Output

1

HINT

 

100%的数据N<=10000,M<=50000
 
970558 ws_fqk 1051 Accepted 3712 kb 96 ms C++/Edit 2371 B 2015-05-12 15:31:34
970484 ws_fqk 1051 Wrong_Answer 3468 kb ms C++/Edit 2374 B 2015-05-12 14:48:33
970467 ws_fqk 1051 Runtime_Error 3476 kb ms C++/Edit 2365 B 2015-05-12 14:35:52

 

第一遍不知道为何RE……第二遍变量名打错WA,找了半个多小时(555555),奇怪的是还得了30分。。。发现后就A掉了。

分析:

对于某连通块内的牛,是相互喜欢的,所以可以tarjan找出这样的连通块然后缩成一个点。再重新构图。

然后找出度为0的点,即为答案。否则无解,若有两个及以上出度为0的点也无解(因为出度为0的点之间不能相互喜欢)。

第一次写tarjan……

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int head[50001],next[50001],list[50001],head0[50001],next0[50001],list0[50001],dfn[50001],low[50001],stack[50001],belong[50001],num[50001];
int n,m,tot,tot0,top,cnt,sum,ans,a,b;
bool inset[50001];
void insert(int a,int b)
{
     tot++;
     next[tot]=head[a];
     head[a]=tot;
     list[tot]=b;
}
void insert0(int a,int b)
{
     next0[++tot0]=head0[a];
     head0[a]=tot0;
     list0[tot0]=b;
}
void dfs(int x)
{
     dfn[x]=low[x]=++sum;
     stack[++top]=x;
     inset[x]=1;
     int y=head[x];
     while (y!=0)
     {
           if (!dfn[list[y]])
           {
                           dfs(list[y]);
                           low[x]=min(low[x],low[list[y]]);
           }
           if (inset[list[y]]&&dfn[list[y]]<low[x]) low[x]=dfn[list[y]];
           y=next[y];
     }
     y=-1;
     if (dfn[x]==low[x])
     {
                        cnt++;
                        while (y!=x)
                        {
                              y=stack[top--];
                              inset[y]=0;
                              belong[y]=cnt;
                              num[cnt]++;
                        }
     }
}
void rebuild()
{
     int y;
     for (int i=1;i<=n;i++)
     {
         y=head[i];
         while (y!=0)
         {
               if (belong[i]!=belong[list[y]]) insert0(belong[i],belong[list[y]]);
               y=next[y];
         }
     }
}
void tarjan()
{
     for (int i=1;i<=n;i++) if (!dfn[i]) dfs(i);
}
int main()
{
    tot=0; sum=0; top=0; cnt=0; tot0=0; ans=0;
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(inset,0,sizeof(inset));
    memset(belong,0,sizeof(belong));
    memset(num,0,sizeof(num));
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d",&a,&b);
        insert(a,b);
    }
    tarjan();
    rebuild();
    for (int i=1;i<=cnt;i++)
        if (!head0[i]) {if (ans) {ans=0; break;} else ans=num[i];}
    printf("%d\n",ans);
    return 0;
}                  

 

posted @ 2015-05-12 15:29  ws_fqk  阅读(203)  评论(0编辑  收藏  举报