题目传送门

解题思路:

先求强联通分量,缩点,然后统计新图中有几个点出度为0,如果大于1个,则说明这不是一个连通图,答案即为0.否则入度为0的那个强连通分量的点数即为答案

AC代码:

 #include<iostream>
#include<cstdio>
#include<stack>
#include<set> using namespace std; int daan,n,m,head[],tot;
int dfn[],low[],sum,rp;
int belong[],_head[],num[];
bool vis[];
struct kk{
int to,next;
}e[],a[];
stack<int> s;
set<int> ans[]; inline void add(int x,int y) {
e[++tot].to = y;
e[tot].next = head[x];
head[x] = tot;
} inline void tarjan(int x) {
dfn[x] = low[x] = ++sum;
int v;
s.push(x);
vis[x] = ;
for(int i = head[x];i != ; i = e[i].next) {
v = e[i].to;
if(!dfn[v]) {
tarjan(v);
low[x] = min(low[x],low[v]);
}
else if(vis[x])
low[x] = min(low[x],dfn[v]);
}
if(dfn[x] == low[x]) {
rp++;
do {
v = s.top();
s.pop();
belong[v] = rp;
num[rp]++;
vis[x] = false;
}
while(v != x);
}
} inline void _add(int x,int y) {
a[++tot].to = y;
a[tot].next = _head[x];
_head[x] = tot;
} inline void findin() {
for(int i = ;i <= rp; i++)
for(int j = _head[i];j != ; j = a[j].next) {
int o = a[j].to;
ans[i].insert(o);
}
} int main() {
scanf("%d%d",&n,&m);
for(int i = ;i <= m; i++) {
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i = ;i <= n; i++)
if(!dfn[i]) //求强连通分量
tarjan(i);
tot = ;
for(int i = ;i <= n; i++)//构建新图,其实没啥必要
for(int j = head[i];j != ; j = e[j].next)
if(belong[i] != belong[e[j].to])
_add(belong[i],belong[e[j].to]);
findin();
for(int i = ;i <= rp; i++)//找入度为0的点
if(ans[i].size() == ) {
if(daan != ) {
printf("");
return ;
}
daan = i;
}
printf("%d",num[daan]);
return ;
}

第一次的做法,用了set,较麻烦

 #include<iostream>
#include<cstdio>
#include<stack>
#include<set> using namespace std; int daan,n,m,head[],tot;
int _out[],dfn[],low[];
int sum,rp,belong[];
int _head[],num[];
bool vis[];
struct kk{
int to,next;
}e[],a[];
stack<int> s; inline void add(int x,int y) {
e[++tot].to = y;
e[tot].next = head[x];
head[x] = tot;
} inline void tarjan(int x) {
dfn[x] = low[x] = ++sum;
int v;
s.push(x);
vis[x] = ;
for(int i = head[x];i != ; i = e[i].next) {
v = e[i].to;
if(!dfn[v]) {
tarjan(v);
low[x] = min(low[x],low[v]);
}
else if(vis[x])
low[x] = min(low[x],dfn[v]);
}
if(dfn[x] == low[x]) {
rp++;
do {
v = s.top();
s.pop();
belong[v] = rp;
num[rp]++;
vis[x] = false;
}
while(v != x);
}
} inline void _add(int x,int y) {
a[++tot].to = y;
a[tot].next = _head[x];
_head[x] = tot;
} int main() {
scanf("%d%d",&n,&m);
for(int i = ;i <= m; i++) {
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i = ;i <= n; i++)
if(!dfn[i])
tarjan(i);
tot = ;
for(int i = ;i <= n; i++)
for(int j = head[i];j != ; j = e[j].next)
if(belong[i] != belong[e[j].to])
_out[belong[i]]++;
for(int i = ;i <= rp; i++)
if(_out[i] == ) {
if(daan != ) {
printf("");
return ;
}
daan = i;
}
printf("%d",num[daan]);
return ;
}

改进后的代码,发现不用set,比较精简

洛谷 P2341 [HAOI2006]受欢迎的牛|【模板】强连通分量的更多相关文章

  1. 【题解】洛谷P2341 [HAOI2006]受欢迎的牛(强连通分量)

    洛谷P2341:https://www.luogu.org/problemnew/show/P2341 前言 这题看错题目 足足花了将近5小时提交了15次 在一位dalao的提醒下才AC了 记得要看清 ...

  2. 洛谷 P2341 [HAOI2006]受欢迎的牛 解题报告

    P2341 [HAOI2006]受欢迎的牛 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所有奶 牛都是自恋狂,每头奶牛总是喜欢自己的.奶牛之间的"喜欢&q ...

  3. 洛谷——P2341 [HAOI2006]受欢迎的牛//POJ2186:Popular Cows

    P2341 [HAOI2006]受欢迎的牛/POJ2186:Popular Cows 题目背景 本题测试数据已修复. 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所 ...

  4. 洛谷P2341 [HAOI2006]受欢迎的牛 (Tarjan,SCC缩点)

    P2341 [HAOI2006]受欢迎的牛|[模板]强连通分量 https://www.luogu.org/problem/P2341 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就 ...

  5. 【模板】Tarjan缩点,强连通分量 洛谷P2341 [HAOI2006]受欢迎的牛 [2017年6月计划 强连通分量01]

    P2341 [HAOI2006]受欢迎的牛 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所有奶 牛都是自恋狂,每头奶牛总是喜欢自己的.奶牛之间的“喜欢”是可以传递的 ...

  6. 洛谷P2341 [HAOI2006]受欢迎的牛|【模板】强连通分量

    https://www.luogu.org/problem/P2341 缩点之后唯一 一个出度为0的点 #include<cstdio> #include<iostream> ...

  7. 洛谷 P2341 [HAOI2006]受欢迎的牛

    题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所有奶 牛都是自恋狂,每头奶牛总是喜欢自己的.奶牛之间的“喜欢”是可以传递的——如果A喜 欢B,B喜欢C,那么A也喜欢C ...

  8. POJ——T2186 Popular Cows || 洛谷——P2341 [HAOI2006]受欢迎的牛

    http://poj.org/problem?id=2186 || https://www.luogu.org/problem/show?pid=2341 Time Limit: 2000MS   M ...

  9. 洛谷 P2341 [HAOI2006]受欢迎的牛 题解

    今天学了强连通分量的Tarjan算法,做了这道类似于板子题的题(尽管我调了1.5h).主要的思路是用Tarjan缩点之后,求每个点的入度(实际上是出度,因为我是反着连边的).如果 有且只有一个点的入度 ...

随机推荐

  1. LCA之tarjan离线

    显然81篇题解是有点多了,不让我提交. 更为不好的是没有一篇详细的\(tarjan\)(不过我也不会写详细的). 不过\(tarjan\)并没有我们想象的那样难理解,时间也并不爆炸(巧妙的跳过难写二字 ...

  2. UVA 12510/CSU 1119 Collecting Coins DFS

    前年的省赛题,难点在于这个石头的推移不太好处理 后来还是看了阳神当年的省赛总结,发现这个石头这里,因为就四五个子,就暴力dfs处理即可.先把石头当做普通障碍,进行一遍全图的dfs或者bfs,找到可以找 ...

  3. pyhton scipy最小二乘法(scipy.linalg.lstsq模块)

    最小二乘法则是一种统计学习优化技术,它的目标是最小化误差平方之和来作为目标J(θ)J(θ),从而找到最优模型. 7. SciPy最小二乘法 最小二乘法则是一种统计学习优化技术,它的目标是最小化误差平方 ...

  4. IIC协议解析

    (1)概述 I2C(Inter-Integrated Circuit BUS) 集成电路总线,该总线由NXP(原PHILIPS)公司设计,多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距 ...

  5. POJ 2829 Buy Tickets

    Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 26443   Accepted: 12639 Des ...

  6. 浅析Java NIO

    浅析Java NIO 前言   在说NIO之前,先来说说IO的读写原理.我们都知道Java中的IO流可以分为网络IO流和文件IO流,前者在网络中使用,后者在操作文件时使用.但实际上两种流区别并不是太大 ...

  7. Mac安装软件提示破损

    安装提示破损 zhong终端输入 sudo spctl --master-disable 就可以顺利打开啦

  8. win下的常用8个命令

    windows下常用的几个指令 一,ping 它是用来检查网络是否通畅或者网络连接速度的命令.作为一个生活在网络上的管理员或者黑客来说,ping命令是第一个必须掌握的DOS命令,它所利用的原理是这样的 ...

  9. 学校算法作业X——(日期问题)

    最近一直在忙项目,难得有时间写一下作业,所以断了,现在赶紧续上 题目如下: 日历问题 问题描述 在我们现在使用的日历中, 闰年被定义为能被4整除的年份,但是能被100整除而不能被400整除的年是例外, ...

  10. Struts+Hibernate+Spring面试题合集及答案(转)

    Struts+Hibernate+Spring面试题合集及答案 Struts+Hibernate+Spring 面试题合集 1 1. Hibernate部分 2 1.1. Hibernate工作原理 ...