洛谷 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受欢迎. 这 种关系是具有传递性的,如 ...
随机推荐
- ASP.NET MVC 认证模块报错:“System.Configuration.Provider.ProviderException: 未启用角色管理器功能“
新建MVC4项目的时候 选 Internet 应用程序的话,出来的示例项目就自带了默认的登录认证等功能.如果选空或者基本,就没有. 如果没有,现在又想加进去,怎么办呢? 抄啊.将示例项目的代码原原本本 ...
- javase - 点餐系统
public class OrderMsg { public static void main(String[] args) throws Exception { /** * 订餐人姓名.选择菜品.送 ...
- 自己定义NumberPicker
1. 项目中要用DatePicker 做时间选择用.但发现有android自带的好搓,就找了下有没有自己定义的时间选择控件. 找来找去发现github上的都时间控件都比較大.比較占手机屏幕的空间, ...
- node.js怎么配置访问本地的html文件?
node.js怎么配置访问本地的html文件? https://segmentfault.com/q/1010000000251204
- 3.4 存储简单数据的利器——Preferences
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="ht ...
- Java压缩技术(三) ZIP解压缩——Java原生实现
原文:http://snowolf.iteye.com/blog/642492 JavaEye的朋友跟我说:“你一口气把ZIP压缩和解压缩都写到一个帖子里,我看起来很累,不如分开好阅读”.ok,面向读 ...
- PCB Genesis加邮票孔(线与线)实现算法
一.Genesis加邮票孔(线与线)实现算法 1.鼠标点击位置P点, 2.通过P点求出,垂足2个点:P1C与P2C (两个点即距离2条线段垂直的垂足点) 3.计算P1C到P2C方位角(假设置为变量PA ...
- php多个进程写文件
多进程写文件function write_file($filename, $content){ $lock = $filename . '.lck'; $write_length = 0; while ...
- php函数 array_values()
array_values() 函数返回一个包含给定数组中所有键值的数组,但不保留键名. 提示:被返回的数组将使用数值键,从 0 开始并以 1 递增. $a=array("Name" ...
- T - Amusing Joke(map)
Problem description So, the New Year holidays are over. Santa Claus and his colleagues can take a re ...