1051: [HAOI2006]受欢迎的牛

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 4776  Solved: 2542

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
/*这是一个缩点Tarjan求环的裸题 */
#include<iostream>
#include <cstdio>
#include <cstring>
using namespace std; const int Maxn = ;
const int Maxm = ;
struct node
{
int to,next;
} edge[Maxm];
int n,m,head[Maxn],dfn[Maxn],low[Maxn],stack1[Maxn],num[Maxn],du[Maxn],vis[Maxn],cnt,tt,top,cut; void init()
{
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(head,-,sizeof(head));
memset(vis,,sizeof(vis));
memset(num,,sizeof(num));
memset(du,,sizeof(du));
} void addedge(int u,int v)
{
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt;
cnt++;
} void Tarjan(int u,int fa)
{
dfn[u]=tt;
low[u]=tt;
tt++;
vis[u]=;
stack1[top]=u;
top++;
for(int i=head[u]; i!=-; i=edge[i].next)
{
int v=edge[i].to;
if(!vis[v])
{
Tarjan(v,u);
low[u]=min(low[u],low[v]);
}
else if(vis[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u])
{
cut++;
while(top>&&stack1[top]!=u)
{
top--;
vis[stack1[top]]=;
num[stack1[top]]=cut;
}
}
} int main()
{
int u,v;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=; i<m; i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
}
for(int i=; i<=n; i++)
{
if(!vis[i])
{
Tarjan(i,);
}
}
for(int i=; i<=n; i++)
{
for(int j=head[i]; j!=-; j=edge[j].next)
{
if(num[i]!=num[edge[j].to])
{
du[num[i]]++;
}
}
}
int sum=,x;
for(int i=; i<=cut; i++)
{
if(!du[i])
{
sum++;
x=i;
}
}
if(sum==)
{
sum=;
for(int i=; i<=n; i++)
{
if(num[i]==x)
{
sum++;
}
}
printf("%d\n",sum);
}
}
return ;
}

心若向阳,无谓悲伤

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=,M=;
int n=,m=;
int head[N],to[M],next[M],edge=;
int dfn[N],inS[N],idx=,low[N];
int stk[N],top=;
int comp[N],n2=,cnt[N];
int in[N];
int head2[N],to2[M],next2[M],edge2=;
int q[N*],front=,back=,vis[N];
inline void addEdge(int u,int v) {
to[edge]=v,next[edge]=head[u],head[u]=edge++;
}
void tarjan(int x) {
dfn[x]=low[x]=idx++;
stk[top++]=x;
inS[x]=;
for (int e=head[x];~e;e=next[e]) {
int& v=to[e];
if (!dfn[v]) {
tarjan(v);
low[x]=min(low[x],low[v]);
} else if (inS[x])
low[x]=min(low[x],dfn[v]);
}
if (dfn[x]==low[x]) {
++n2;
int u=;
do {
u=stk[--top];
comp[u]=n2;
inS[u]=;
++cnt[n2];
} while (u!=x);
}
}
inline void addEdge2(int u,int v) {
++in[v];
to2[edge2]=v,next2[edge2]=head2[u],head2[u]=edge2++;
}
inline void build() {
for (int i=;i<=n;++i)
for (int e=head[i];~e;e=next[e]) {
int &u=comp[i],&v=comp[to[e]];
if (u!=v)
addEdge2(v,u);
}
}
inline int bfs(int s) {
front=back=;
memset(vis,,sizeof(vis));
q[back++]=s;
vis[s]=;
while (front<back) {
int x=q[front++];
for (int e=head2[x];~e;e=next2[e]) {
int& v=to2[e];
if (!vis[v]) {
q[back++]=v;
vis[v]=;
}
}
}
for (int i=;i<=n2;++i)
if (!vis[i])
return ;
return ;
}
int main(void) {
memset(head,-,sizeof(head));
scanf("%d %d",&n,&m);
while (m--) {
int u=,v=;
scanf("%d %d",&u,&v);
addEdge(u,v);
}
for (int i=;i<=n;++i)
if (!dfn[i])
tarjan(i);
//建缩点以后的反图 就所有入度为0的点bfs
memset(head2,-,sizeof(head2));
build();
int ans=;
for (int i=;i<=n2;++i)
if (!in[i])
if (bfs(i))
ans+=cnt[i];
printf("%d\n",ans);
return ;
}

上个代码在洛谷不过,求大神指点

bzoj1051受欢迎的牛(Tarjan)的更多相关文章

  1. 【bzoj1051】 [HAOI2006]受欢迎的牛 tarjan缩点判出度算点数

    [bzoj1051] [HAOI2006]受欢迎的牛 2014年1月8日7450 Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B ...

  2. 【BZOJ1051】1051: [HAOI2006]受欢迎的牛 tarjan求强连通分量+缩点

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

  3. BZOJ1051:受欢迎的牛(并查集 / Tarjan)

    1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 8161  Solved: 4460 Description ...

  4. [BZOJ1051][HAOI2006] 受欢迎的牛 tarjan求联通分量

    1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 5687  Solved: 3016[Submit][Sta ...

  5. bzoj 1051: [HAOI2006]受欢迎的牛 tarjan缩点

    1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2092  Solved: 1096[Submit][Sta ...

  6. BZOJ 1051: [HAOI2006]受欢迎的牛( tarjan )

    tarjan缩点后, 有且仅有一个出度为0的强连通分量即answer, 否则无解 ----------------------------------------------------------- ...

  7. p2341&bzoj1051 受欢迎的牛

    传送门(洛谷) 传送门(bzoj) 题目 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这 种关系是具有传递性的,如果A认为B受欢迎,B认为C ...

  8. B1051 受欢迎的牛 tarjan缩点

    就是一道tarjan缩点的板子,之前在洛谷做过.但是我发现一个事,就是函数里面有一句话: void tarjan(int x) { dfn[x] = low[x] = ++tot; str[++top ...

  9. BZOJ1051 受欢迎的牛

    http://www.lydsy.com/JudgeOnline/problem.php?id=1051 Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A ...

随机推荐

  1. angular(转)

    学习之前可以看看 知乎上讨论angularjs优缺点 帮你选择框架的网站 同类主流框架对比 教程 angularjs在慕课网 angularjs在51cto angularjs在图灵社区 社区 Ang ...

  2. xcap发包工具的简单使用2(发送报文)

    上一篇文章介绍了如何构造报文,现在简单讲一下发送报文的步骤 1.获取接口列表 点击主界面工具栏中的“刷新列表”按钮(或对应菜单“interface->Reference interfaces”) ...

  3. git详细说明

    https://www.cnblogs.com/qcloud1001/p/9796750.html

  4. 7-8 哈利·波特的考试(25 分)(图的最短路径Floyd算法)

    7-8 哈利·波特的考试(25 分) 哈利·波特要考试了,他需要你的帮助.这门课学的是用魔咒将一种动物变成另一种动物的本事.例如将猫变成老鼠的魔咒是haha,将老鼠变成鱼的魔咒是hehe等等.反方向变 ...

  5. bzoj 1005 [HNOI2008] 明明的烦恼 (prufer编码)

    [HNOI2008]明明的烦恼 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 5907  Solved: 2305[Submit][Status][Di ...

  6. [K/3Cloud] 理解BOS关于Enabled属性的表决器原理

    通常的编程中,我们习惯: btnOK.Enabled = true; 这个样子就会将按钮变成有效,反之亦然.但在ERP的表单中,其某个按钮或字段其有效性及其复杂,例如一个表格中某个数量单元格其有效性是 ...

  7. [bzoj1500][NOI2005]维修数列[Treap][可持久化Treap]

    非旋转式Treap1500 :) #include <bits/stdc++.h> #pragma GCC optimize(3) using namespace std; const i ...

  8. msp430入门编程04

    msp430中C语言的变量与数据类型 msp430入门学习 msp430入门编程

  9. android中SQLite实现

    SQLite操作类: package com.example.administrator.myapplication; import android.content.Context; import a ...

  10. Codeforces 629D Babaei and Birthday Cake(树状数组优化dp)

    题意: 线段树做法 分析: 因为每次都是在当前位置的前缀区间查询最大值,所以可以直接用树状数组优化.比线段树快了12ms~ 代码: #include<cstdio> #include< ...