题目大意:

      每一头牛的愿望就是变成一头最受欢迎的牛。现在有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. node.js渲染页面

    1 在软件中找到nodejs并安装(强调,安装时选默认位置) 2 复制yuedu文件夹到本地 3 在yuedu文件夹中按shift 点击右键 4 输入命令 npm install 5 安装成功后,输入 ...

  2. MiracleSnow网页设计HTML5+CSS3+JS全套视频教程

    终于把这套课程讲完了,虽然时间隔了很长,但也算有始有终了,这是在YY讲课中我自己录的,讲了网页设计的基础,这也是我第一次给那么多人讲课,讲的不好多多包涵. 前几次视频和课件是分开的,后几次都打包在一起 ...

  3. 利用freemarker生成word,word另存为xml文件的标签解析

    http://wenku.baidu.com/link?url=YxTZWVP3ssO-e_Br3LIZVq2xOQnqaSz8gLPiRUDN8NIR_wX2-Z25OqwbVn5kXqGiOFYU ...

  4. CentOS 7下载

    CentOS 7官方下载地址:https://www.centos.org/download/ 转载https://blog.csdn.net/yxwmzouzou/article/details/7 ...

  5. PHP基本语句

    语句分支语句if语句if if.........elseif.......else if.....else if 的嵌套switch语句 循环语句 for 循环 函数 函数的4要素::返回类型,函数名 ...

  6. Win7、win8、win10下实现精准截获Explorer拷贝行为

    介绍了windows下对Explorer的拷贝动作的精确截获,这个在企业数据安全dlp产品系列中减少审计的噪音很有效,方便运营人员做针对性的审计. 在企业数据安全中我通常需要监测用户的拷贝行为,特别像 ...

  7. 算法 - DNA搜索 - Ako Corasick

    场景:从很长的字符串(输入字符串.DNA)中搜索大量固定字符串(字典.基因) 题目:Determining DNA Health | HackerRank 算法:Aho–Corasick algori ...

  8. 描述一下 Intent 和 IntentFilter?

    Android 中通过 Intent 对象来表示一条消息,一个 Intent 对象不仅包含有这个消息的目的地,还可以包含消息的内容,这好比一封 Email,其中不仅应该包含收件地址,还可以包含具体的内 ...

  9. 【8】ie css hack

    1. "\9"   IE6/IE7/IE8/IE9/IE10都生效 "\0"   IE8/IE9/IE10都生效,是IE8/9/10的hack "\9 ...

  10. 四十七:数据库之alembic数据库迁移工具的基本使用

    在一般情况下,如果修改了模型,如增加或者删除了字段,SQLAlchemy是不会更新的,这就需要使用alembic来实现 使用alembic步骤:一:定义好模型二:使用alembic创建一个仓库:ale ...