题目描述

每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶

牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜

欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你

算出有多少头奶牛可以当明星。

输入输出格式

输入格式:

 第一行:两个用空格分开的整数:N和M

 第二行到第M + 1行:每行两个用空格分开的整数:A和B,表示A喜欢B

输出格式:

 第一行:单独一个整数,表示明星奶牛的数量

输入输出样例

输入样例#1:

3 3
1 2
2 1
2 3
输出样例#1:

1

说明

只有 3 号奶牛可以做明星

【数据范围】

10%的数据N<=20, M<=50

30%的数据N<=1000,M<=20000

70%的数据N<=5000,M<=50000

100%的数据N<=10000,M<=50000

感想

2019年8月16日12:39:48:看自己博客学新算法

最近在纠结写博客那么详细会不会太浪费时间了,毕竟只是给自己或者周围人看的……但今天再次开始搞tarjan,发现自己就写了这一篇文章,还那么简略……以至于还要去其他博客学习……不过我看出来了,当时的代码里,b数组没必要,判断每一条边时使用e数组就好

2019年8月16日13:27:54 重新写了一遍,WA了,原因是tarjan函数里,把u点入栈以后忘记更新instack数组了。加上就A了(但出栈的时候还是忘记更新instack数组了,所以第二份代码是有锅的。不过也A了,这到底是没必要,还是数据水……留坑)。重写画了半个小时,好长啊,中途还磕磕绊绊,比如tarjan内部的几种判断的顺序啥的……

解题思路

  tarjan找到强连通分量,然后缩点,统计缩了之后每个强连通分量的出度,如果只有一个出度为零的强连通分量,答案就是这个强连通分量里点的个数;如果出度为零的强连通分量不止一个,那么答案就为0。

  记得Neil做这题的时候曾经疑惑过——如果缩点后得到的图还是成环咋办?那么所有强连通分量出度都不为零了,答案应该为0,但事实上应该所有奶牛都受欢迎了……原来这个算法正确性是这么保证的——tarjan算法有一个性质:求出的强连通分量一定是极大强连通分量,所以缩出来的点肯定不会成环。

源代码

2017年7月2日的

#include<cstdio>
#include<algorithm> int n,m; struct edge{
int u,v;
}b[]; struct Edge{
int nxt,to;
}e[];
int head[]={},cnt=;
void add(int u,int v)
{
e[cnt]={head[u],v};
head[u]=cnt++;
} int id[]={},index=;
int num[]={}; int dfn[]={},low[]={},dfs_time=;
int stack[]={},top=;
bool instack[]={};
void tarjan(int u)
{
low[u]=dfn[u]=++dfs_time;
stack[top++]=u;
instack[u]=;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(!dfn[v])
tarjan(v),low[u]=std::min(low[v],low[u]);
else if(instack[v])
low[u]=std::min(low[v],low[u]);
}
if(dfn[u]==low[u])
{
index++;
int v;
do{
v=stack[--top];
stack[top]=;
id[v]=index,instack[v]=;
num[index]++;
}while(v!=u);
}
} int out[]={}; int main()
{
//freopen("cow.in","r",stdin);
//freopen("cow.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=,u,v;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
b[i]={u,v};
}
for(int i=;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int i=;i<=m;i++)
if(id[b[i].u]!=id[b[i].v])
out[id[b[i].u]]++; int ans=;
for(int i=;i<=index;i++)
if(!out[i])
{
if(ans)
{
printf("0\n");
return ;
}
else ans=num[i];
}
printf("%d\n",ans);
return ;
}

2019年8月16日13:39:02更新——

 #include<cstdio>
#include<algorithm> const int MAXN=1e4+,MAXM=5e4+; int n,m; struct Edge{
int nxt,to;
}e[MAXM];
int cnt=,head[MAXN];
inline void add(int u,int v)
{
e[cnt]={head[u],v};
head[u]=cnt++;
} int dfn[MAXN],low[MAXN],dfst=;//时间戳们
int stack[MAXN],top=;
bool instack[MAXN];
int id[MAXN],index=;//缩点用的新id
int num[MAXN];//统计每个强连通分量大小
int out[MAXN];//统计各强连通分量出度
void tarjan(int u)
{
dfn[u]=low[u]=dfst++;//打时间戳
stack[++top]=u;//入栈
instack[u]=;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(!dfn[v])//树边
{
tarjan(v);
low[u]=std::min(low[u],low[v]);
}
else if(instack[v])//返祖边
{
low[u]=std::min(low[u],low[v]);//暂时先更新low,不急着出栈,以便找到极大强连通分量
}
}
if(low[u]==dfn[u])//得割点一个,出栈缩点
{
do//为啥都在栈里来着?
{
id[stack[top--]]=index;
num[index]++;//这句话可以放在外面O(1)处理
}while(stack[top+]!=u);
index++;
}
} int main()
{
scanf("%d%d",&n,&m);
for(int i=,u,v;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
}
for(int i=;i<=n;i++)
{
if(!dfn[i]) tarjan(i);
} for(int u=;u<=n;u++)//统计出度
{
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(id[u]!=id[v])
{
out[id[u]]++;
}
}
}
int ans=;
for(int i=;i<index;i++)
{
if(!out[i])
{
if(ans)
{
puts("");
return ;
}
ans=num[i];
}
}
printf("%d\n",ans);
return ;
}

洛谷 P2341 BZOJ 1051 [HAOI2006]受欢迎的牛的更多相关文章

  1. BZOJ 1051: [HAOI2006]受欢迎的牛 缩点

    1051: [HAOI2006]受欢迎的牛 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/ ...

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

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

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

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

  4. BZOJ 1051: [HAOI2006]受欢迎的牛(SCC)

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

  5. BZOJ 1051: [HAOI2006]受欢迎的牛

    Description 一个有向图,求所以能被别的点到达的点的个数. Sol Tarjan + 强连通分量 + 缩点. 缩点以后找强连通分量,缩点,然后当图有且仅有1个出度为1的点时,有答案. Cod ...

  6. BZOJ 1051: [HAOI2006]受欢迎的牛 强连通缩点

    题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1051 题解: 强连通缩点得到DAG图,将图转置一下,对入度为零的点跑dfs看看能不能访问 ...

  7. bzoj 1051: [HAOI2006]受欢迎的牛 (Tarjan 缩点)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1051 思路: 首先用Tarjan把环缩成点,要想收到所有人的欢迎,那么这个点的出度必为0,且 ...

  8. bzoj 1051 [HAOI2006]受欢迎的牛(tarjan缩点)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1051 题解:缩点之后判断出度为0的有几个,只有一个那么输出那个强连通块的点数,否者 ...

  9. 【BZOJ 1051】 1051: [HAOI2006]受欢迎的牛 (SCC)

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

随机推荐

  1. PL/SQL Developer使用技巧、快捷键(转发)

    转发自:https://www.cnblogs.com/linjiqin/archive/2013/06/24/3152538.html PL/SQL Developer使用技巧.快捷键 1.类SQL ...

  2. 通过命令行升级git for windows

    git update-git-for-windows 配置了正确的代理,就可以通过命令行直接升级.最好是可以访问谷歌的代理,否则国内的网络通过命令行升级,下载到一半,就会失败.

  3. tflearn中num_epoch含义就是针对所有样本的一次迭代

    In tensorflow get started code: import tensorflow as tf import numpy as np features = [tf.contrib.la ...

  4. HDU 3887 Counting Offspring(DFS序+树状数组)

    Counting Offspring Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  5. poj--1101--The Game(bfs)

    The Game Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9746   Accepted: 2967 Descript ...

  6. js getyear和getfullyear

    getyear()函数如果今年是2015年会得到115,getfullyear()会得到完整的年份.

  7. Django day11(一) ajax 文件上传 提交json格式数据

    一: 什么是ajax? AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”.即使用Javascript语言与服务器进行异步交互 ...

  8. ACM_名字的价值

    名字的价值 Time Limit: 2000/1000ms (Java/Others) Problem Description: 集训终于开始了,参加集训的人很多,也就有很多名字,集训组织者发现了一件 ...

  9. 开启远程MySQL

    安装完MySQL,由于安全原因默认是没有赋予用户远程权限的,所以第一步要首先赋予用户对应的权限 一  授权 mysql> mysql -u用户名 [-pIp地址] -p #登录 mysql> ...

  10. struts2结果处理、获取参数(二)

    结果处理 1.转发 type可以不写,默认就是转发 <package name="hello" namespace="/hello" extends=&q ...