传送门啦

这个题就是tarjan强连通分量与入度的例题了。

思路:

利用缩点的思想,先预处理一下所有的强连通分量,然后把每个强连通分量内的所有节点看做一个节点,然后处理一张新图,然后检查每个点的入度,然后取入度为 0 的点(缩点后)的个数,即为信息出发点。

可能有人想问为什么??

大体说明一下:

1.充分性证明:如果入度为 0 的点不是信息出发点,那么这个点必定不会接收到任何节点发出的信息,因为它的入度为 0 。

2.必要性证明:如果信息出发点不是入度为0的点,那么其必有入度点,使其覆盖点更多,而我们要找至少多少个点。

还是先明确一下各个数组的意思吧:

 dfn[i]:i点的时间戳

 low[i],表示这个点以及其子孙节点连的所有点中dfn最小的值

 stack[],表示当前所有可能能构成是强连通分量的点。

 ins[i],表示 i 是否在stack[ ]数组中

 num[i],表示第 i 个强连通分量中有多少个点

 belong[i],表示第 i 点在哪一个强连通分量里

 in[i]:表示第 i 个强连通分量的入度是多少。

以下就是怎么处理入度:

	for(int i=1;i<=m;i++){
if(belong[edge[i].from] != belong[edge[i].to])
in[belong[edge[i].to]]++;
}

解释一下:

枚举边,比较这条边起点和终点是否在同一个强连通分量中,如果不在,这条边终点的入度++

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 5;
const int maxm = 5e5 + 6; int n,m,u,v;
int head[maxn],tot;
int dfn[maxn],low[maxn],ind;
int stack[maxn],top,belong[maxn],num[maxn],cnt;
int in[maxn];//表示某个点的入度
int ans;
bool ins[maxn];
struct Edge{
int from,to,next;
}edge[maxm]; void add(int u,int v){
edge[++tot].to = v;
edge[tot].from = u;
edge[tot].next = head[u];
head[u] = tot;
} int read(){
char ch = getchar();
int f = 1 , x = 0;
while(ch > '9' || ch < '0'){
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
} void tarjan(int x){
dfn[x] = low[x] = ++ind;
stack[++top] = x;
ins[x] = true;
for(int i=head[x];i;i=edge[i].next){
int v = edge[i].to;
if(ins[v]) low[x] = min(low[x] , dfn[v]);
if(!dfn[v]){
tarjan(v);
low[x] = min(low[v] , low[x]);
}
}
int k;
if(dfn[x] == low[x]){
++cnt;
do{
k = stack[top];
num[cnt]++;
top--;
ins[k] = false;
belong[k] = cnt;
} while(k != x);
}
} int main(){
n = read(); m = read();
for(int i=1;i<=m;i++){
u = read(); v = read();
add(u , v);
}
for(int i = 1;i <= n ;++i) belong[i] = i;
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i); for(int i=1;i<=m;i++){
if(belong[edge[i].from] != belong[edge[i].to])
in[belong[edge[i].to]]++;
}
for(int i=1;i<=cnt;i++)
if(in[i] == 0)
ans++;
printf("%d\n",ans);
return 0;
}

洛谷P2002消息扩散的更多相关文章

  1. tarjan算法比较详细的讲解&&tarjan常见疑难解答&&洛谷P2002 消息扩散题解

    因为有大佬写的比我更长更具体,所以我也就写写总结一下了 引入: 众所周知,很多图中有个东西名叫环. 对于这个东西很多算法都很头疼.(suchas 迪杰斯特拉) 更深层:环属于强联通分量(strongl ...

  2. 洛谷—— P2002 消息扩散

    P2002 消息扩散 题目背景 本场比赛第一题,给个简单的吧,这 100 分先拿着. 题目描述 有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市 ...

  3. 洛谷P2002 消息扩散

    题目背景 本场比赛第一题,给个简单的吧,这 100 分先拿着. 题目描述 有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市发布消息才能让这所有n ...

  4. 洛谷 P2002 消息扩散

    题目背景 本场比赛第一题,给个简单的吧,这 100 分先拿着. 题目描述 有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市发布消息才能让这所有n ...

  5. Luogu P2002 消息扩散&&P1262 间谍网络

    怕自己太久没写Tarjan了就会把这种神仙算法忘掉. 其实这种类型的图论题的套路还是比较简单且显然的. P2002 消息扩散 很显然的题目,因为在一个环(其实就是强连通分量)中的城市都只需要让其中一个 ...

  6. 题解【洛谷P2002】消息扩散

    题面 题解 \(Tarjan\)裸题. \(Tarjan\)缩点后统计入度为\(0\)的强连通分量个数,输出即可. 代码 #include <iostream> #include < ...

  7. P2002 消息扩散(缩点)

    描述:https://www.luogu.com.cn/problem/P2002 有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市发布消息才能 ...

  8. P2002 消息扩散[SCC缩点]

    题目描述 有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市发布消息才能让这所有n个城市都得到消息. 输入格式 第一行两个整数n,m表示n个城市, ...

  9. 【luogu P2002 消息扩散】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2002 缩点把原图变为DAG,再在DAG上判断找入度为0的点的个数. 注意一点出度为0的点的个数不等于入度为0 ...

随机推荐

  1. PHP 性能分析第一篇: Intro to Xhprof & Xhgui

    [前言]这是国外知名博主 Davey Shafik所撰写的 PHP 应用性能分析系列的第一篇,阅读第二篇可深入了解 xhgui,第三篇则关注于性能调优实践. 原文链接如下: https://blog. ...

  2. struts2 的自定义 拦截器

    Struts2的 拦截器: 对于拦截器,Struts2官方给出的 定义是: 拦截器是动态拦截Action调用的对象.它提供了一种机制,使开发者可以定义一段代码,在Action执行之前或者之后被调用执行 ...

  3. Android Studio怎么文件添加到收藏和打开收藏夹

    http://jingyan.baidu.com/article/1709ad809e608b4634c4f0b9.html 在使用Android studio编写的代码的过程中,有时会碰到有一些文件 ...

  4. Android Layout: TableLayout

    TableLayout<TableLayout xmlns:android="http://schemas.android.com/apk/res/android" andr ...

  5. bzoj 4358: permu 莫队

    第一步先莫队分块. 对于每一块l~r,初始右端点设为r+1,然后每个询问先将右端点往右移,然后处理询问在l~r之间的部分,最后用一个栈再把l~r的复原. 具体来说是维护两个数组now1和now2,一个 ...

  6. codeforces contest 1111

    A. Superhero Transformation 题意: 元音和元音,辅音和辅音字母之间可以互相转换,问两个字符串是否想同: 题解:直接判断即可: #include<bits/stdc++ ...

  7. 四、Linux学习之文件处理命令

    1.建立目录:mkdir 格式:mkdir –p [目录名] -p     递归创建目录 注意事项: 如果是创建单个目录直接mkdir [目录名就可以] 如果是创建一个目录下的目录也就是递归创建目录请 ...

  8. Kubernetes--kubectl

    一.Kubectl命令行说明 类型 命令 描述 基础命令 create  通过文件名或标准输入创建资源 expose  将一个资源公开为一个新的kubernetes服务 run 创建并运行一个特定的镜 ...

  9. python中的zip

    >>> a = zip([1,2,3],[34,35,36]) >>> print(a) <zip object at 0x0394D0F8> > ...

  10. java中的悲观锁和乐观锁实现

    悲观锁就是认为并发时一定会有冲突发生,采用互斥的策略.比如java中的synchronized. 而乐观锁是假设并发时不会有冲突发生,如果发生冲突,则操作失败,并不断重试.乐观锁的机制就是CAS(Co ...