题目大意:

      每一头牛的愿望就是变成一头最受欢迎的牛。现在有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. Makefile样例

    Makefile1 src = $(wildcard ./*cpp) obj = $(patsubst %.cpp, %.o,$(src)) target = test $(target) : $(o ...

  2. Java面试题收集(二)

    四.Redis简介 redis为什么这么快 4.1 Redis数据类型 String hash 字典,适用于存储对象 list 安照String元素插入顺序排序,最新插入的最先显示.如热点数据 set ...

  3. Alpha发布--美工+文案

    此作业对应要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/8677 一.美工: 1.产品logo 2.原型页面展示 2.1 进入萌 ...

  4. springboot2.x 整合redis集群的几种方式

    一.不指定redis连接池 #系统默认连接池 yml配置文件: spring: redis: cluster: nodes: - 192.168.1.236:7001 - 192.168.1.236: ...

  5. Error-ASP.NET:编译器错误消息: CS0016: 未能写入输出文件

    ylbtech-Error-ASP.NET:编译器错误消息: CS0016: 未能写入输出文件 1.返回顶部 1. “/”应用程序中的服务器错误. 编译错误 说明: 在编译向该请求提供服务所需资源的过 ...

  6. Python之变量以及类型

    为了更充分的利用内存空间以及更有效率的管理内存,变量是有不同的类型的,如下所示: 怎样知道一个变量的类型呢? 在python中,只要定义了一个变量,而且它有数据,那么它的类型就已经确定了,不需要咱们开 ...

  7. JavaScript中二进制与10进制互相转换

    webpack打包生成的代码中涉及了一些二进制位与的操作, 所以今天来学习一下JavaScript中的二进制与十进制转换操作吧 十进制转二进制: var num = 100 num.toString( ...

  8. 拉取代码产生冲突 && 切换分支

    1.拉取代码产生冲突 项目中用的主要是 IDEA 编辑器,拉取代码时产生冲突的时候,就先 add + commit 一下,然后再拉取代码,这样子就不冲突了. 拉取过后再push一次. 2.切换一个新增 ...

  9. 40组合总和II

    题目:给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合.candidates 中的每个数字在每个组合中只能使用一 ...

  10. git 新建项目提交本地项目代码

    git init git remote add origin ssh://git@42.123.127.93:10022/tyshawn/sdap1.git git add . git commit ...