题目大意:

      每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
牛被所有的牛认为是受欢迎的。
 
      先用tarjan求出每个强连通分量,再缩点,统计每个点的出度,如果有且只有1个出度为0的点,就输出这个点包含的节点数,否则输出0.
 
证明:
      如果有强连通分量被孤立(即和其他强连通分量无边相连),那么答案一定是0,此时由于缩点后是一个DAG图,出度为0的点的个数一定大于1.
      如果没有点被孤立,当出度为0的点多于1个时,由DAG图的性质可得,一定不存在一个点能从其他所有点到达。只有当出度为0的点的个数等于1时,这个出度为0的点才能被其他所有点到达。
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define cls(s,h) memset(s,h,sizeof s)
const int maxn = 1e5 + ;
int n , m ;
int tot;
struct edge
{
int to,from,nxt;
}e[maxn << ]; int head[maxn];
void add_edge(int u , int v ){
e[tot].from = u ;
e[tot].to = v;
e[tot].nxt = head[u];
head[u] = tot++;
} int stack[maxn << ],low[maxn << ],dfn[maxn << ];
int scc,sz[maxn << ],c[maxn << ],st,num;
void init(){
cls(head,-);
cls(e,);
cls(sz,);
scc = ;
st = ;
} void tanjan(int u){
stack[++st] = u;
dfn[u] = low[u] = ++ num;
for(int i = head[u],v; ~i ;i = e[i].nxt){
if(c[v = e[i].to]) continue;
if(dfn[v]) low[u] = min(low[u],dfn[v]);
else tanjan(v),low[u] = min(low[u],low[v]);
}
if(low[u] == dfn[u]){
c[u] = ++ scc; sz[scc] = ;
while(st && u != stack[st])
//SCC number and the scc ge SCC
c[stack[st--]] = scc,sz[scc] ++;
st--;
}
} int out[maxn << ];
int main(int argc, char const *argv[])
{
init();
scanf("%d %d",&n,&m);
for(int i = ,u,v;i <= m ;i ++)
scanf("%d %d",&u,&v),add_edge(u,v); for(int i = ;i <= n;i ++)
if(!dfn[i]) tanjan(i);
for(int i = ;i < tot;i ++)
if(c[e[i].from] != c[e[i].to]) out[c[e[i].from]] ++;
int ans = ;
for(int i = ;i <= scc;i ++)
if(!out[i]) ans = ans ? -: i;
if(~ans) ans = sz[ans];
else ans = ;
printf("%d\n", ans);
return ;
}
//如果没有点被孤立,当出度为0的点多于1个时,
//由DAG图的性质可得,一定不存在一个点能从其他所有点到达。
//只有当出度为0的点的个数等于1时,
//这个出度为0的点才能被其他所有点到达。
//因为如果存在两个,那么就会少一个点
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define cls(s,h) memset(s,h,sizeof s)
const int maxn = 1e5 + ;
int n , m ;
int tot;
struct edge
{
int to,from,nxt;
}e[maxn << ]; int head[maxn];
void add_edge(int u , int v ){
e[tot].from = u ;
e[tot].to = v;
e[tot].nxt = head[u];
head[u] = tot++;
} int stack[maxn << ],low[maxn << ],dfn[maxn << ];
int scc,sz[maxn << ],c[maxn << ],st,num;
void init(){
cls(head,-);
cls(e,);
cls(sz,);
scc = ;
st = ;
} void tanjan(int u){
stack[++st] = u;
dfn[u] = low[u] = ++ num;
for(int i = head[u],v; ~i ;i = e[i].nxt){
if(c[v = e[i].to]) continue;
if(dfn[v]) low[u] = min(low[u],dfn[v]);
else tanjan(v),low[u] = min(low[u],low[v]);
}
if(low[u] == dfn[u]){
c[u] = ++ scc; sz[scc] = ;
while(st && u != stack[st])
//强连通分量的编号和其中点的个数
//SCC number and the scc ge SCC
c[stack[st--]] = scc,sz[scc] ++;
st--;
}
} int out[maxn << ];
int main(int argc, char const *argv[])
{
init();
scanf("%d %d",&n,&m);
for(int i = ,u,v;i <= m ;i ++)
scanf("%d %d",&u,&v),add_edge(u,v); for(int i = ;i <= n;i ++)
if(!dfn[i]) tanjan(i);
for(int i = ;i < tot;i ++)
if(c[e[i].from] != c[e[i].to]) out[c[e[i].from]] ++;
int ans = ;
for(int i = ;i <= scc;i ++)
if(!out[i]) ans = ans ? -: i;
if(~ans) ans = sz[ans];
else ans = ;
printf("%d\n", ans);
return ;
}

更新代码

poj2186--tarjan+缩点(有向图的强连通分量中点的个数)的更多相关文章

  1. Tarjan算法初探 (1):Tarjan如何求有向图的强连通分量

    在此大概讲一下初学Tarjan算法的领悟( QwQ) Tarjan算法 是图论的非常经典的算法 可以用来寻找有向图中的强连通分量 与此同时也可以通过寻找图中的强连通分量来进行缩点 首先给出强连通分量的 ...

  2. Tarjan算法 求 有向图的强连通分量

    百度百科 https://baike.baidu.com/item/tarjan%E7%AE%97%E6%B3%95/10687825?fr=aladdin 参考博文 http://blog.csdn ...

  3. Tarjan算法求有向图的强连通分量

    算法描述 tarjan算法思想:从一个点开始,进行深度优先遍历,同时记录到达该点的时间(dfn记录到达i点的时间),和该点能直接或间接到达的点中的最早的时间(low[i]记录这个值,其中low的初始值 ...

  4. 『Tarjan算法 有向图的强连通分量』

    有向图的强连通分量 定义:在有向图\(G\)中,如果两个顶点\(v_i,v_j\)间\((v_i>v_j)\)有一条从\(v_i\)到\(v_j\)的有向路径,同时还有一条从\(v_j\)到\( ...

  5. UVA247- Calling Circles(有向图的强连通分量)

    题目链接 题意: 给定一张有向图.找出全部强连通分量,并输出. 思路:有向图的强连通分量用Tarjan算法,然后用map映射,便于输出,注意输出格式. 代码: #include <iostrea ...

  6. uva11324 有向图的强连通分量+记忆化dp

    给一张有向图G, 求一个结点数最大的结点集,使得该结点集中任意两个结点u和v满足,要么u可以到达v, 要么v可以到达u(u和v相互可达也可以). 因为整张图可能存在环路,所以不好使用dp直接做,先采用 ...

  7. poj2186Popular Cows(Kosaraju算法--有向图的强连通分量的分解)

    /* 题目大意:有N个cows, M个关系 a->b 表示 a认为b popular:如果还有b->c, 那么就会有a->c 问最终有多少个cows被其他所有cows认为是popul ...

  8. 图->连通性->有向图的强连通分量

    文字描述 有向图强连通分量的定义:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly co ...

  9. DFS的运用(二分图判定、无向图的割顶和桥,双连通分量,有向图的强连通分量)

    一.dfs框架: vector<int>G[maxn]; //存图 int vis[maxn]; //节点访问标记 void dfs(int u) { vis[u] = ; PREVISI ...

随机推荐

  1. python学习之路(9)

    函数的参数 定义函数的时候,我们把参数的名字和位置确定下来,函数的接口定义就完成了.对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复杂逻辑被封装起来,调 ...

  2. HashMap、Hashtable、HashSet三种hash集合的区别

    转载:http://www.cnblogs.com/lzrabbit/p/3721067.html#h1 HashMap和Hashtable的区别 两者最主要的区别在于Hashtable是线程安全,而 ...

  3. Mysql和Orcale的区别

    有很多应用项目, 刚起步的时候用MYSQL数据库基本上能实现各种功能需求,随着应用用户的增多,数据量的增加,MYSQL渐渐地出现不堪重负的情况:连接很慢甚至宕机,于是就有把数据从MYSQL迁到ORAC ...

  4. maven国内镜像、国内外仓库(直接下载jar)

    阿里: https://maven.aliyun.com/mvn/search 官方: http://repo.maven.apache.org/maven2/ maven仓库 阿里巴巴的镜像仓库, ...

  5. 一起学vue指令之v-pre

    一起学vue指令之v-pre 一起学 vue指令 v-pre  指令可看作标签属性 浏览器解析引擎遇到vue的插值符号时会自动解析,当你想输出不被解析的纯文本时,可以使用v-pre指令. 未使用v-p ...

  6. PHP 设置Cookie值注意项

    Cookie 中的value值只能添加设置为String类型的字符串数据,但我们需要添加如数组,json串等其他类型的数据时,我们就要先对数据进行转换,再存入Cookie里了. Cookie 存储数组 ...

  7. [MVC HtmlHelper简单了解]

    HtmlHelper用来在视图中显示Html控件,简化代码,使用方便!,降低了View视图中的代码复杂度!可以更快速的完成工作! 以下是一些常用 的html标签 辅助方法 使用HTML辅助方法输出   ...

  8. Oracle非分区索引,全局分区索引和本地分区索引。

    1.如果按照索引是否分区作为划分依据,Oracle 的索引类型可以分为非分区索引,全局分区索引和本地分区索引. 2.创建演示实例 --创建非分区表create table test_partition ...

  9. puppeteer - 操作支付宝报“操作频繁”错误的思考

    我这里想要实现的是通过转账到支付宝的方式判断一个手机号是否注册过支付宝.但查询收款人的网络请求很复杂分析不出来,使用 puppteer 也是没有解决 "操作频繁" 的问题(应该还有 ...

  10. HTML基础之DOM

    DOM(Document Object Model 文档对象模型) 一个web页面的展示,是由html标签组合成的一个页面,js是一门语言,dom对象实际就是将html标签转换成了一个文档对象.可以通 ...