题目大意:

      每一头牛的愿望就是变成一头最受欢迎的牛。现在有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. JavaScript 的基本概念( ES5 )

    语法 区分大小写 标识符 第一个字符必须是一个字母,下划线或者一个美元符( $ ).其他规则无论,最好按照通用的驼峰大小写. 注释 // 单行注释 /* 多行注释 */ 严格模式 在顶部添加如下代码 ...

  2. fiddler(二)、配置抓取https协议

    打开fiddler,用火狐或者谷歌浏览器访问https协议的网页,如:https://www.baidu.com/,会报不安全的连接错误 这时就需要我们做一些配置,才能抓取https协议的网页. 首先 ...

  3. css彩色(渐变)文字

    css彩色文字也称渐变文字 在张鑫旭博客首页看到这效果,就自己研究了一下. 实现方法加个背景然后在根据文本剪切,再把文本填充为透明色让之前设置的背景颜色显示出来即可. -webkit-backgrou ...

  4. Android学习_7/22

    一.Android项目目录结构 1.         AndroidManifest.xml:整个Android项目的配置,注册各组件 <activity android:name=" ...

  5. Python set 用法

    (原文链接)http://blog.csdn.net/business122/article/details/7541486# python的set和其他语言类似, 是一个无序不重复元素集, 基本功能 ...

  6. TCP 之 TCP首部

    TCP首部图 TCP首部说明 源端口,目的端口 用于寻找发送端和接收端应用进程.(源IP,源端口,目的IP,目的端口) 四元组确定唯一一个TCP连接:(IP,端口)也称为一个插口(socket): 序 ...

  7. jQuery Validate 验证成功时的提示信息

    大多数时候我们使用validate进行前台验证的时候,都是验证错误的时候给出提示信息,最近在做一个项目的时候,想这验证成功后给出一个验证成功的提示.于是在网上找了一些资料. <!doctype ...

  8. SQL 表 数据备份

    insert into SMTTemporarySave select * from [MSV0CIMDB].[PICS_20170706].dbo.SMTTemporarySave

  9. 代码实现:有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。

    import java.util.ArrayList; import java.util.List; import java.util.Scanner; //有n个人围成一圈,顺序排号.从第一个人开始 ...

  10. 详析静态网站与动态网站区别(服务器ip dns 端口)

    几个基本知识 1.服务器:能够提供服务的机器 取决于机器上所安装的服务软件     1) web服务器:提供web服务(网站访问) 就需要安装web服务软件,Apache,tomcat,iis等 2. ...