洛谷 P2341 BZOJ 1051 [HAOI2006]受欢迎的牛
题目描述
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶
牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜
欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你
算出有多少头奶牛可以当明星。
输入输出格式
输入格式:
第一行:两个用空格分开的整数:N和M
第二行到第M + 1行:每行两个用空格分开的整数:A和B,表示A喜欢B
输出格式:
第一行:单独一个整数,表示明星奶牛的数量
输入输出样例
3 3
1 2
2 1
2 3
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]受欢迎的牛的更多相关文章
- BZOJ 1051: [HAOI2006]受欢迎的牛 缩点
1051: [HAOI2006]受欢迎的牛 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/ ...
- bzoj 1051: [HAOI2006]受欢迎的牛 tarjan缩点
1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2092 Solved: 1096[Submit][Sta ...
- BZOJ 1051: [HAOI2006]受欢迎的牛( tarjan )
tarjan缩点后, 有且仅有一个出度为0的强连通分量即answer, 否则无解 ----------------------------------------------------------- ...
- BZOJ 1051: [HAOI2006]受欢迎的牛(SCC)
1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 8172 Solved: 4470[Submit][Sta ...
- BZOJ 1051: [HAOI2006]受欢迎的牛
Description 一个有向图,求所以能被别的点到达的点的个数. Sol Tarjan + 强连通分量 + 缩点. 缩点以后找强连通分量,缩点,然后当图有且仅有1个出度为1的点时,有答案. Cod ...
- BZOJ 1051: [HAOI2006]受欢迎的牛 强连通缩点
题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1051 题解: 强连通缩点得到DAG图,将图转置一下,对入度为零的点跑dfs看看能不能访问 ...
- bzoj 1051: [HAOI2006]受欢迎的牛 (Tarjan 缩点)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1051 思路: 首先用Tarjan把环缩成点,要想收到所有人的欢迎,那么这个点的出度必为0,且 ...
- bzoj 1051 [HAOI2006]受欢迎的牛(tarjan缩点)
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1051 题解:缩点之后判断出度为0的有几个,只有一个那么输出那个强连通块的点数,否者 ...
- 【BZOJ 1051】 1051: [HAOI2006]受欢迎的牛 (SCC)
1051: [HAOI2006]受欢迎的牛 Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这 种关系是具有传递性的,如 ...
随机推荐
- JS中split使用方法和数组中元素的删除
JS中split使用方法和数组中元素的删除 JS中split使用方法 <script language="javascript"> function spli(){ d ...
- C++模板(菜鸟教程)
C++模板(菜鸟教程) C++ 模板 模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码. 模板是创建泛型类或函数的蓝图或公式.库容器,比如迭代器和算法,都是泛型编程的例子,它们都 ...
- poi读取docx中的文字和图片(自己应用)
poi读取docx中的文字和图片(自己应用) package com.fry.poiDemo.dao; import java.io.File; import java.io.FileInputStr ...
- python nltk 入门demo
sudo pip install -U pyyaml nltk import nltk nltk.download() 搞不定,必须代理: Installing via a proxy web ser ...
- [SpringMVC]定义多个前缀映射的问题
转自:https://penciltim.iteye.com/blog/501073 我在web.xml里面定义多个dispatch-servlet的前缀映射,像下面这样 <!-- Servle ...
- MySQL优化小方法
一.查询优化 1.尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引: 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而 ...
- mybatis中if标签判断字符串相等问题
mybatis 映射文件中,if标签判断字符串sfyx变量是否是字符串Y的时候,发现并不管用: <if test="sfyx=='Y' "> and 1=1 </ ...
- 《CSS Mastery》读书笔记(4)
第七章 布局 CSS得到一个不好的名声,比较难懂, 一方面由于浏览器的不兼容,另一方面由于网上大量的技巧,每个CSS作者都可以有自己的方法去创建多列布局, 新的CSS开发者只是使用一种方法而不去理 ...
- div自动适应浏览器窗口水平和垂直居中
html <body> <div id="centerDiv">自动适应水平和垂直居中</div> </body> css ;;} ...
- Morse理论:拓扑不变性特征匹配原理
设计精美的宽基线双目相机镇文 Mo'ersi lilun莫尔斯理论(卷名:数学) Morse theory 微分拓扑的一个重要分支.通常是指两部分内容:一部分是微分流形上可微函数的莫尔斯理论,即临界点 ...