[HAOI2006][BZOJ1051] 受欢迎的牛
1051: [HAOI2006]受欢迎的牛
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 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
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 | 4 ms | C++/Edit | 2374 B | 2015-05-12 14:48:33 |
970467 | ws_fqk | 1051 | Runtime_Error | 3476 kb | 4 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; }