Popular Cows
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 30680   Accepted: 12445

Description

Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M <= 50,000) ordered pairs of the form (A, B) that tell you that cow A thinks that cow B is popular. Since popularity is transitive, if A thinks B is popular and B thinks C is popular, then A will also think that C is 
popular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow. 

Input

* Line 1: Two space-separated integers, N and M

* Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular.

Output

* Line 1: A single integer that is the number of cows who are considered popular by every other cow. 

Sample Input

3 3
1 2
2 1
2 3

Sample Output

1

大意:n只牛,m对数(a,b)表示a认为b牛逼。若a认为b牛逼,b认为c牛逼,那么a也认为c牛逼。问n只牛中,有多少只牛是其他所有牛都认为牛逼的。

分析:若图为不连通,则答案为0.当图连通时,在同一个强连通分量A中的牛在被该强连通分量中其他牛认为牛逼;若在A和另一个强连通分量B之间有路,假设A指向B,则A中的牛都认为B中的牛是牛逼的。任意一个有向图都可以分解成若干不相交的强连通分量,把每个强连通分量缩点,就得到一个DAG(有向无环图)。该题要找的是缩点后DAG中出度为0的点所表示的强连通分量中的点数。(该出度为0的点一定唯一,否则不可能有其他牛都认为牛逼的牛)

求强连通分量可使用tarjan算法。
Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。

定义DFN(u)为节点u搜索的次序编号(时间戳),Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号。

当DFN(u)=Low(u)时,以u为根的搜索子树上所有节点是一个强连通分量
 
void tarjan(int s)
{
vis[s]=;
dfn[s]=low[s]=++now;
sta.push(s);
for(int i=; i<gra[s].size(); i++)
{
int t=gra[s][i];
if(dfn[t]==)
{
tarjan(t);
low[s]=min(low[s],low[t]);
}
else if(vis[t]==)
low[s]=min(low[s],dfn[t]);
}
if(low[s]==dfn[s])
{
sum++;
while(!sta.empty())
{
int t=sta.top();
sta.pop();
vis[t]=;
num[t]=sum;
if(t==s)
break;
}
}
}

 AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#include<vector>
#include<stack>
using namespace std;
#define LL long long
#define N 10005
vector<int> gra[N];
stack<int>sta;
int n,m,dfn[N],low[N],vis[N],num[N];
int degree[N],sum,now,res,loc;
void init()
{
sum=;
now=;
res=;
memset(vis,,sizeof(vis));
memset(low,,sizeof(low));
memset(dfn,,sizeof(dfn));
memset(degree,,sizeof(degree));
for(int i=; i<=n; i++)
gra[i].clear();
while(!sta.empty())
sta.pop();
} void read()
{
int a,b;
scanf("%d%d",&n,&m);
for(int i=; i<m; i++)
{
scanf("%d%d",&a,&b);
gra[a].push_back(b);
}
} void tarjan(int s)
{
vis[s]=;
dfn[s]=low[s]=++now;
sta.push(s);
for(int i=; i<gra[s].size(); i++)
{
int t=gra[s][i];
if(dfn[t]==)
{
tarjan(t);
low[s]=min(low[s],low[t]);
}
else if(vis[t]==)
low[s]=min(low[s],dfn[t]);
}
if(low[s]==dfn[s])
{
sum++;
while(!sta.empty())
{
int t=sta.top();
sta.pop();
vis[t]=;
num[t]=sum; //缩点
if(t==s)
break;
}
}
} void solve()
{
for(int i=; i<=n; i++)
if(!dfn[i])
tarjan(i);
for(int i=; i<=n; i++)
for(int j=; j<gra[i].size(); j++)
if(num[i]!=num[gra[i][j]])
degree[num[i]]++; //对缩点后的DAG进行出度的统计
for(int i=; i<=sum; i++)
{
if(degree[i]==)
{
res++;
loc=i; //第几个强连通分量
}
}
if(res>)
printf("0\n");
else
{
res=;
for(int i=; i<=n; i++)
if(num[i]==loc)
res++;
printf("%d\n",res);
}
} int main()
{ init();
read();
solve();
return ;
}
/*
3 3
1 2
2 1
2 3 */
 

POJ_2186_Popular Cows_强连通分量的更多相关文章

  1. HDU5934 强连通分量

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5934 根据距离关系建边 对于强连通分量来说,只需引爆话费最小的炸弹即可引爆整个强连通分量 将所有的强连通分 ...

  2. POJ1236Network of Schools[强连通分量|缩点]

    Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16571   Accepted: 65 ...

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

    Tarjan算法 Tarjan算法是基于dfs算法,每一个强连通分量为搜索树中的一颗子树.搜索时,把当前搜索树中的未处理的结点加入一个栈中,回溯时可以判断栈顶到栈中的结点是不是在同一个强连通分量中.当 ...

  4. Tarjan算法--强连通分量

    tarjan的过程就是dfs过程. 图一般能画成树,树的边有三种类型,树枝边 + 横叉边(两点没有父子关系) + 后向边(两点之间有父子关系): 可以看到只有后向边能构成环,即只有第三张图是强连通分量 ...

  5. 强连通分量的一二三 | | JZOJ【P1232】 | | 我也不知道我写的什么

    贴题: 在幻想乡,上白泽慧音是以知识渊博闻名的老师.春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄.因此慧音决定换一个能够聚集最多人数的村庄作为新的教学地点.人间之 ...

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

    有向图强连通分量的Tarjan算法 [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G ...

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

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

  8. Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)【转】【修改】

    一.基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成 ...

  9. POJ 1236 Network of Schools(强连通分量/Tarjan缩点)

    传送门 Description A number of schools are connected to a computer network. Agreements have been develo ...

随机推荐

  1. Tkinter图形界面设计(GUI)

    [因为这是我第一个接触的GUI图形界面python库,现在也不用了,所以大多数内容都来自之前花 钱买的一些快速入门的内容,可以当作简单的知识点查询使用] 在此声明:内容来自微信公众号GitChat,付 ...

  2. Java基础——基础数据类型与读入输出

    首先我们写完了HelloWorld就学会了java的一种输出 System.out.println() 用起来就像是被强化过的C++的puts函数 或者就是自带endl的cout函数,中间的" ...

  3. noip模拟赛 Chtholly Nota Seniorious

    题目背景 大样例下发链接: https://pan.baidu.com/s/1nuVpRS1 密码: sfxg こんなにも.たくさんの幸せをあの人に分けてもらった だから.きっと 今の.私は 谁が何と ...

  4. N天学习一个Linux命令之ln

    前言有时候同一个文件想创建多个别名,这个时候可以使用链接文件代替 用途对文件或者目录创建链接,默认创建的是硬链接 硬链接Linux底层文件系统由超级数据块,目录树对象,inode索引节点对象,文件对象 ...

  5. HDU 1561&HDU 3449 一类简单依赖背包问题

    HDU 1561.这道是树形DP了,所谓依赖背包,就是选A前必须选B,这样的问题.1561很明显是这样的题了.把0点当成ROOT就好,然后选子节点前必须先选根,所以初始化数组每一行为该根点的值.由于多 ...

  6. 【cocos2d-x 3.7 飞机大战】 决战南海I (十) 游戏主场景

    主场景要包括其它类的头文件 #include "cocos2d.h" #include "MyPlane.h" #include "Bullet.h& ...

  7. Swoole源代码学习记录(十二)——ReactorThread模块

    Swoole版本号:1.7.5-stable Github地址:https://github.com/LinkedDestiny/swoole-src-analysis 这一章将分析Swoole的Re ...

  8. hdu 1010 Tempter of the Bone (奇偶性剪枝)

    题意:有一副二维地图'S'为起点,'D'为终点,'.'是可以行走的,'X'是不能行走的.问能否只走T步从S走到D? 题解:最容易想到的就是DFS暴力搜索,,但是会超时...=_=... 所以,,要有其 ...

  9. luogu1514 引水入城

    题目大意 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个NN 行\times M×M 列的矩形,如上图所示,其中每个格子都代表一座城市,每座城市 ...

  10. bootstrap简单form表单样式-form-horizontal

    jsp代码: <div id="content" style="background-color: white;"> <form class= ...