有N(N<=10000)头牛,每头牛都想成为most poluler的牛,给出M(M<=50000)个关系,如(1,2)代表1欢迎2,关系可以传递,但是不可以相互,即1欢迎2不代表2欢迎1,但是如果2也欢迎3那么1也欢迎3.
给出N,M和M个欢迎关系,求被所有牛都欢迎的牛的数量。
用强联通分量做
首先求出联通分量的个数,然后依次求各个联通分量的出度,如果仅有一个连通分量出度为0则这个联通分量内的点的个数就是答案; 所以在用KO算法的时候还要判短是否这个最后的连通分量都可达
 
KO算法
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
const int MAX_V = ;
int V; // 顶点数
vector<int> G[MAX_V]; // 图的邻接表表示
vector<int> rG[MAX_V]; // 把边反向后的图
vector<int> vs; // 后序遍历顺序的顶点列表
bool used[MAX_V]; // 访问标记
int cmp[MAX_V]; // 所属强连通分量的拓扑序322 第 4 章 登峰造极——高级篇
void add_edge(int from, int to)
{
G[from].push_back(to);
rG[to].push_back(from);
}
void dfs(int v)
{
used[v] = true;
for (int i = ; i < G[v].size(); i++)
{
if (!used[G[v][i]]) dfs(G[v][i]);
}
vs.push_back(v);
}
void rdfs(int v, int k)
{
used[v] = true;
cmp[v] = k;
for (int i = ; i < rG[v].size(); i++)
{
if (!used[rG[v][i]]) rdfs(rG[v][i], k);
}
}
int scc()
{
memset(used, , sizeof(used));
vs.clear();
for (int v = ; v < V; v++)
{
if (!used[v]) dfs(v);
}
memset(used, , sizeof(used));
int k = ;
for (int i = vs.size() - ; i >= ; i--)
{
if (!used[vs[i]]) rdfs(vs[i], k++);
}
return k;
} int main( )
{
int n,m;
scanf("%d%d",&n,&m);
V=n;
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
u-- ; v-- ;
add_edge(u,v);
}
n=scc();
int u=-,ans=,fa=;
for(int i= ; i<V ; i++)
{
if(cmp[i]==n-)///最后一个拓扑序
{ u=i;
ans++;
}
}
///检查是否从所有点可达
memset(used,false,sizeof(used));
rdfs(u,);//在跑一遍dfs,利与之后判断可达
for(int i= ; i<V ; i++)
{
if(!used[i])
{
ans=;
break;
}
}
if(fa==)
printf("%d\n",ans);
else
puts("");
}

TA算法

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <stack>
using namespace std;
#define M 1000009
vector<int> edge[M];
stack<int> ss;
int n,m,tot,scc;
int low[M],DFN[M],belong[M];
int out[M],num[M];
bool instack[M];
void init()
{
for(int i = ;i < n;i++)
{
edge[i].clear();
}
tot = ;
scc = ;
while(!ss.empty()) ss.pop();
memset(low,,sizeof(low));
memset(DFN,,sizeof(DFN));
memset(out,,sizeof(out));
memset(belong,,sizeof(belong));
}
void add_edge(int u,int v)
{
edge[u].push_back(v);
}
void tarjan(int u)
{
instack[u] = true;
low[u] = DFN[u] = ++tot;
ss.push(u); //将刚访问的节点入栈
for(int i = ;i < edge[u].size();i++)
{
int v = edge[u][i];
if(!DFN[v]) //没有被访问过
{ // (不能写成不在栈中,因为在栈中的一定是访问过的,但是不在栈中的也可能访问过,只是已经划入之前的强连通分量了)
tarjan(v);
low[u] = min(low[u],low[v]);
}
else if(instack[v]) // 指向栈中节点的后向边
{
low[u] = min(low[u],DFN[v]);
}
}
if(DFN[u] == low[u]) // u 为一个强连通分量的根
{
scc++;//强连通分量的编号
int v;
do
{
v = ss.top();
ss.pop();
belong[v] = scc; //标记每个节点所在的强连通分量
num[scc]++; //每个强连通分量的节点个数
}while(u != v);
}
}
int main( )
{
init();
scanf("%d%d",&n,&m);
for(int i= ; i<m ; i++)
{
int u,v;
scanf("%d%d",&u,&v);
add_edge(u-,v-);
}
for(int i= ; i<n ; i++)
{
if(!DFN[i])
tarjan(i);
} for(int i= ; i<n ; i++)
{
for(int j= ; j<edge[i].size() ; j++)
{
int v=edge[i][j];
if(belong[i]!=belong[v])
out[belong[i]]++;//出度
}
}
int sum=;
int ans=;
for(int i= ; i<=scc ; i++)
{
if(!out[i])//答案在出度为0的连通分量
{
sum++;
ans = num[i];///这个连通分量的数目
}
}
if(sum==)///肯定只有一个,因为假设有两个的话,这两个不可能是连通的
printf("%d\n",ans);
else
printf("0\n"); }

poj2186-Popular Cows(强连通分支)的更多相关文章

  1. 强连通分量tarjan缩点——POJ2186 Popular Cows

    这里的Tarjan是基于DFS,用于求有向图的强联通分量. 运用了一个点dfn时间戳和low的关系巧妙地判断出一个强联通分量,从而实现一次DFS即可求出所有的强联通分量. §有向图中, u可达v不一定 ...

  2. 洛谷——P2341 [HAOI2006]受欢迎的牛//POJ2186:Popular Cows

    P2341 [HAOI2006]受欢迎的牛/POJ2186:Popular Cows 题目背景 本题测试数据已修复. 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所 ...

  3. POJ2186 Popular Cows [强连通分量|缩点]

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 31241   Accepted: 12691 De ...

  4. POJ2186 Popular Cows 【强连通分量】+【Kosaraju】+【Tarjan】+【Garbow】

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 23445   Accepted: 9605 Des ...

  5. 【Tarjan缩点】POJ2186 Popular Cows

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 35644   Accepted: 14532 De ...

  6. poj2186 Popular Cows 题解——S.B.S.

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 29642   Accepted: 11996 De ...

  7. POJ-2186 Popular Cows,tarjan缩点找出度为0的点。

    Popular Cows 题意:一只牛崇拜另外一只牛,这种崇拜关系可以传导.A->B,B->C =>A->C.现在给出所有的关系问你有多少牛被其他所有的牛都崇拜. 思路:就是一 ...

  8. POJ2186 Popular Cows

    Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= ...

  9. POJ2186 Popular Cows(强连通分量)

    题目问一个有向图所有点都能达到的点有几个. 先把图的强连通分量缩点,形成一个DAG,那么DAG“尾巴”(出度0的点)所表示的强连通分量就是解,因为前面的部分都能到达尾巴,但如果有多个尾巴那解就是0了, ...

  10. POJ2186 Popular Cows 强连通分量tarjan

    做这题主要是为了学习一下tarjan的强连通分量,因为包括桥,双连通分量,强连通分量很多的求法其实都可以源于tarjan的这种方法,通过一个low,pre数组求出来. 题意:给你许多的A->B ...

随机推荐

  1. android SDK manager 无法获取更新版本列表【转载】

    http://mirrors.neusoft.edu.cn/eclipse/releases/luna/打开这个网址就可以看到adt的详细信息:  http://developer.android.c ...

  2. noip寻找道路

    题目描述 在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 1 .路径上的所有点的出边所指向的点都直接或间接与终点连通. 2 .在满足条 ...

  3. 第二次C语言实验报告

    #一.设计题目,设计思路,实现方法 ##设计题目 15-10 找最长的字符串,14-5 指定位置输出字符串,13-6 数组循环右移,12-5 查找指定字符,11-5 打印杨辉三角. ##设计思路 15 ...

  4. HDOJ1213(并查集)

    set容器中的值互异,非常好用. 水题,直接贴代码了 #include<iostream> #include<cstdio> #include<set> using ...

  5. 二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历

    二叉搜索树的结构(30 分) 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值:若它的右子树不空,则右子树上所有结点的值均大于它的根 ...

  6. Linux如何打开执行脚本

    命令行下例如要打开startmysql.sh就直接 sh /目录/目录当前界面下就简单了在这个SH文件目录下打开终端 输入 sh startmysql.sh 回车或者对这个文件右键 打开 选择“在终端 ...

  7. linux strace-跟踪进程的系统调用或是信号产生情况,lstrace-跟踪己丑年调用库函数情况,进程跟踪调试命令

    本工具可以用来做大多数排除,比如mount一个NFS,很慢,找不出原因,我们可以使用strace命令来跟中mount这个经常所有的调用过程. strace 命令是一种强大的工具,它能够显示所有由用户空 ...

  8. 1.JasperReports学习笔记1-了解JasperReports

    转自:http://www.blogjava.net/vjame/archive/2013/10/12/404908.html JasperReports是一个开源的java报表制作引擎,官网地址:h ...

  9. kvm ip查看

    1.virsh --list(查看有哪些服务器) 2.virsh dumpxml 虚拟机名称 查看服务器对应的mac地址 3.然后再宿主机上arp -a 查看对应的mac地址对应的ip

  10. Java泛型通配符以及限定

    摘抄笔记 A:泛型的限定 /* * 将的酒店员工,厨师,服务员,经理,分别存储到3个集合中 * 定义方法,可以同时遍历3集合,遍历三个集合的同时,可以调用工作方法 */ import java.uti ...