传送门

参考资料:

  [1]:挑战程序设计竞赛

题意:

  每头牛都想成为牛群中的红人。

  给定N头牛的牛群和M个有序对(A, B),(A, B)表示牛A认为牛B是红人;

  该关系具有传递性,所以如果牛A认为牛B是红人,牛B认为牛C是红人,那么牛A也认为牛C是红人。

  不过,给定的有序对中可能包含(A, B)和(B, C),但不包含(A, C)。

  求被其他所有牛认为是红人的牛的总数。

分析(摘抄自挑战程序设计竞赛):

  考虑以牛为顶点的有向图,对每个有序对(A, B)连一条从 A到B的有向边;

  那么,被其他所有牛认为是红人的牛对应的顶点,也就是从其他所有顶点都可达的顶点。

  虽然这可以通过从每个顶点出发搜索求得,但总的复杂度却是O(NM),是不可行的,必须要考虑更为高效的算法。

  假设有两头牛A和B都被其他所有牛认为是红人,那么显然,A被B认为是红人,B也被A认为是红人;

  即存在一个包含A、B两个顶点的圈,或者说,A、B同属于一个强连通分量。

  反之,如果一头牛被其他所有牛认为是红人,那么其所属的强连通分量内的所有牛都被其他所有牛认为是红人。

  由此,我们把图进行强连通分量分解后,至多有一个强连通分量满足题目的条件。

  而按前面介绍的算法进行强连通分量分解时,我们还能够得到各个强连通分量拓扑排序后的顺序;

  唯一可能成为解的只有拓扑序最后的强连通分量。

  所以在最后,我们只要检查这个强连通分量是否从所有顶点可达就好了。

  该算法的复杂度为O(N+M),足以在时限内解决原题。

对红色字体的理解:

  满足条件的强连通分量的特点是(红牛所在的强连通分量):

    (1)出度为0

    (2)其余的节点都会间接或直接的指向此强连通分量的任一节点

  再结合向量vs 的作用,在Dfs( )中,vs中存储的第一个节点肯定是满足条件的强连通分量中的某一节点;

  在vs中,越靠前的节点的拓扑序越大。

AC代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=1e5+; int n,m;
int num;
int head[maxn];
struct Edge
{
int to;
int next;
}G[*maxn];
void addEdge(int u,int v)
{
G[num]={v,head[u]};
head[u]=num++;
}
struct SCC
{
int col[maxn];
bool vis[maxn];
vector<int >vs;
void DFS(int u)
{
vis[u]=true;
for(int i=head[u];~i;i=G[i].next)
{
int v=G[i].to;
if((i&) || vis[v])//正向边,num为偶数
continue;
DFS(v);
}
vs.push_back(u);
}
void RDFS(int u,int k)
{
vis[u]=true;
col[u]=k;
for(int i=head[u];~i;i=G[i].next)
{
int v=G[i].to;
if(!(i&) || vis[v])//反向边,num为奇数
continue;
RDFS(v,k);
}
}
int scc()
{
vs.clear();
mem(vis,false);
for(int i=;i <= n;++i)
if(!vis[i])
DFS(i); int k=;
mem(vis,false);
for(int i=vs.size()-;i >= ;--i)//从拓扑序的最大值开始查找SCC
if(!vis[vs[i]])
RDFS(vs[i],++k);
return k;
}
}_scc;
int Solve()
{
int k=_scc.scc();
int ans=;
int u;
for(int i=;i <= n;++i)
if(_scc.col[i] == k)
{
ans++;
u=i;
}
mem(_scc.vis,false);
_scc.RDFS(u,);//再次调用RDFS()判断u是否可以到达其他任意节点
for(int i=;i <= n;++i)
if(!_scc.vis[i])
return ;
return ans;
}
void Init()
{
num=;
mem(head,-);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
Init();
for(int i=;i <= m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
addEdge(u,v);
addEdge(v,u);
}
printf("%d\n",Solve());
}
return ;
}

poj 2186 "Popular Cows"(强连通分量入门题)的更多相关文章

  1. poj 2186 Popular Cows (强连通分量+缩点)

    http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissi ...

  2. POJ 2186 Popular Cows 强连通分量模板

    题意 强连通分量,找独立的块 强连通分量裸题 #include <cstdio> #include <cstdlib> #include <cstring> #in ...

  3. POJ 2186 Popular Cows --强连通分量

    题意:给定一个有向图,问有多少个点由任意顶点出发都能达到. 分析:首先,在一个有向无环图中,能被所有点达到点,出度一定是0. 先求出所有的强连通分支,然后把每个强连通分支收缩成一个点,重新建图,这样, ...

  4. POJ 2186 Popular Cows(强连通分量缩点)

    题目链接:http://poj.org/problem?id=2186 题目意思大概是:给定N(N<=10000)个点和M(M<=50000)条有向边,求有多少个“受欢迎的点”.所谓的“受 ...

  5. poj 2186: Popular Cows(tarjan基础题)

    题目链接 tarjan参考博客 题意:求在图上可以被所有点到达的点的数量. 首先通过tarjan缩点,将所有内部两两可达的子图缩为一点,新图即为一个有向无环图(即DAG). 在这个DAG上,若存在不止 ...

  6. 强连通分量分解 Kosaraju算法 (poj 2186 Popular Cows)

    poj 2186 Popular Cows 题意: 有N头牛, 给出M对关系, 如(1,2)代表1欢迎2, 关系是单向的且能够传递, 即1欢迎2不代表2欢迎1, 可是假设2也欢迎3那么1也欢迎3. 求 ...

  7. poj 2186 Popular Cows 【强连通分量Tarjan算法 + 树问题】

    题目地址:http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Sub ...

  8. POJ 2186 Popular Cows (强联通)

    id=2186">http://poj.org/problem? id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 655 ...

  9. tarjan缩点练习 洛谷P3387 【模板】缩点+poj 2186 Popular Cows

    缩点练习 洛谷 P3387 [模板]缩点 缩点 解题思路: 都说是模板了...先缩点把有环图转换成DAG 然后拓扑排序即可 #include <bits/stdc++.h> using n ...

随机推荐

  1. mysql操作命令梳理(1)-索引

    1.创建索引索引的创建可以在CREATE TABLE语句中进行,也可以单独用CREATE INDEX或ALTER TABLE来给表增加索引.以下命令语句分别展示了如何创建主键索引(PRIMARY KE ...

  2. HTML5-indexedDB使用常见错误总结

    indexedDB使用过程中常常会出现以下错误: Failed to execute ‘createObjectStore’ on ‘IDBDatabase’: The database is not ...

  3. hover设定触发时间间隔

    500毫秒执行一次 $(".banner_menu_content li a").hover(function(){ var aa=$(this).text().trim(); s ...

  4. 阅读<构建之法>10、11、12章

    第十章: 典型用户和场景对后面工作有什么帮助吗? 第十一章: 每日构建的目的是什么呢?有没有具体说明? 第十二章: 产品定位人群是否也局限了产品的可拓展性?

  5. 第六次作业-my Backlog

    杨灵超小组 My  Backlog                                小学生四则运算自动生成(Backlog) ID Name IMP EST How   to Demo ...

  6. chrome启用flash不询问

    69版本之后 打开 chrome://flags/#enable-ephemeral-flash-permission 把它从Default改为Disabled 重新打开Chrome,进入 chrom ...

  7. docker网络调试过程

    #1: 添加永久网桥 vi /etc/sysconfig/network-scripts/ifcfg-br0 DEVICE=br0 TYPE=Bridge BOOTROTO=static IPADDR ...

  8. vue中eventbus被多次触发(vue中使用eventbus踩过的坑)【bus.$on事件被多次绑定】

    问题描述:只要页面没有强制刷新,存在组件切换,bus.$on方法会被多次绑定,造成事件多次触发   触发bus.$on中绑定的方法.png   bus.$on多次绑定.png 解决办法:在每次调用方法 ...

  9. Zabbix的简单使用

    0. 卸载mariadb 安装mysql 方法 rpm -qa |grep mariadb 然后 rpm -e --nodeps mariadb***** 安装mysql # 下载mysql源安装包 ...

  10. Fantacy团队周二站立会议

    词频分析模型 1.这次站会是周二开的,但是由于我个人的疏忽,哎,不说了. 2.会议时间:2016年3月29日12:03~12:30. 持续时长:27分钟 会议参加成员:组长:杨若鹏 http://ww ...