「拓扑排序」可达性统计

可达性统计

原题链接:可达性统计

题目大意

给你一张\(n\)个点\(m\)条边的有向无环图,分别统计从每个点出发能够到达的点的数量

题目题解

看到题意就知道要用到拓扑排序,但是拓扑排序的理论复杂度在30000的极限条件下会超时,这个时候我们考虑使用 \(bitset\),一个很好用的代替bool的防卡常技巧,详细的说明这里不说,可以去百度上查看相关运用

//#define fre yes

#include <queue>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <algorithm>

const int N = 30005;
int head[N << 1], to[N << 1], ver[N << 1];
int in[N], ans[N];

std::bitset<N> f[N];

int tot, k;
void addedge(int x, int y) {
    ver[tot] = y;
    to[tot] = head[x];
    head[x] = tot++;
}

int n, m;

void toposort() {
    std::queue<int> q;
    for (int i = 1; i <= n; i++) {
        if(!in[i]) q.push(i);
    }

    while(!q.empty()) {
        int t = q.front(); q.pop();
        ans[++k] = t;
        for (int i = head[t]; ~i; i = to[i]) {
            int v = ver[i];
            in[v]--;
            if(!in[v]) q.push(v);
        }
    }
}

int main() {
    memset(head, -1, sizeof(head));
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        addedge(u, v);
        in[v] ++;
    } toposort();
    // for (int i = 1; i <= n; i++) {
    //     printf("%d ", ans[i]);
    // }

    for (int  i = n; i >= 1; i--) {
        int j = ans[i];
        f[j][j] = 1;
        for (int x = head[j]; ~x; x = to[x]) {
            f[j] |= f[ver[x]];
        }
    }

    for (int i = 1; i <= n; i++) {
        printf("%d\n", f[i].count());
    } return 0;
}

原文地址:https://www.cnblogs.com/Nicoppa/p/11549865.html

时间: 2024-11-01 11:38:49

「拓扑排序」可达性统计的相关文章

AcWing:164. 可达性统计(拓扑排序 + 状态压缩算法)

给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条有向边. 输出格式 输出共N行,表示每个点能够到达的点的数量. 数据范围 1≤N,M≤300001≤N,M≤30000 输入样例: 10 10 3 8 2 3 2 5 5 9 5 9 2 3 3 9 4 8 2 10 4 9 输出样例: 1 6 3 3 2 1 1 1 1 1 算法:拓扑排序 + 状态压缩算法 题解:首先求出该有向无环图的拓扑

2101 可达性统计

[题目描述] 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. [题目链接] 2101 可达性统计 [算法] 拓扑排序之后逆序计算,bitset状态压缩模拟集合的并操作. [代码] #include <bits/stdc++.h> using namespace std; int n,m,tot,cnt; struct edge{ int to,next; }e[30010]; int head[30010],topn[30010],deg[300

可达性统计

可达性统计 给出一个n个点m条边的有向无环图,求每个点能到达的点的数目,\(n,m\leq 30000\). 解 设\(f[i]\)表示点i能到达的点的状态(其中1表示能够到达,0表示不能到达),显然有30000个点,所以我们无法用long long存下,于是用bitset,问题在于这个方程没有明显的阶段,不能循环实现,于是可以考虑拓扑排序或者是dfs. 参考代码: #include <iostream> #include <cstdio> #include <bitset&

拓扑排序之变量序列算法分析

拓扑排序之变量序列 巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo) 题目描述: 假设有n个变量(1<=n<=26,变量名用单个小写字母表示),还有m个二元组(u,v),分别表示变量u小于v.那么,所有变量从小到大排列起来应该是什么样子的呢? 例如有4个变量a,b,c,d,若以知a<b,c<b,d<c,则这4个变量的排序可能是a<d<c<b.尽管还有可能其他的可能,你只需找出其中的一个即可. 输入: 输入为一

拓扑排序算法

#include<stdio.h>#include<stdlib.h>#define MAXVEX 100 //最大顶点数typedef char VertexType; //顶点typedef int EdgeType; //权值#define UNVISITED -1 //标记未访问#define VISITED 1 //标记未访问#define OK 1#define ERROR 0typedef int Status; typedef struct EdgeNode{ in

bfs 拓扑排序 bnu Usoperanto

题目链接:http://acm.bnu.edu.cn/v3/problem_show.php?pid=39572 题目详细分析:http://talk.icpc-camp.org/d/127-jag-summer-2012-day-4-j-usoperanto 对于这个题目,自己的一点补充(bfs 拓扑排序):在建树的时候,每建立一条边,父亲节点出度+1,因此树叶子节点的出度是为0的(题解里说的入度其实就是在建边的时候父亲节点的出度):那么把所有出度为0的节点压入队列,然后计算这些出度为0的节点

CF 274D Lovely Matrix 拓扑排序,缩点 难度:2

http://codeforces.com/problemset/problem/274/D 这道题解题思路: 对每一行统计,以小值列作为弧尾,大值列作为弧头,(-1除外,不连弧),对得到的图做拓扑排序即可. 但本题数据较大,所以需要进行缩点,把相同数值的点缩在一起,成为一个新的大点,原先的小值列向大点连接,再由大点向大值列连接,可以减少边数 举例来说,原本取值为1的有4个点,取值为2的有5个点, 不缩点,就需要20条边 缩点,只需要4+1+5=10条边 (不过我还是觉得这个方法有点投机取巧??

HDU3342 Legal or Not【拓扑排序】【链式前向星】

Legal or Not Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4633    Accepted Submission(s): 2115 Problem Description ACM-DIY is a large QQ group where many excellent acmers get together. It is

hihocoder 1343 : Stable Members【拓扑排序】

hihocoder #1343:题目 解释:一个学习小组,一共有N个学员,一个主管.每个学员都有自己的导师(一个或者多个),导师可以是其他学员也可以是主管.每周学员都要把自己的学习报告和收到的报告提交给自己的导师,这个团队设计很合理,没有回环(投递出去的报告不会回到自己手中),并且所有的报告最终都会投递到主管那里.但这个团队中有的学员会因为其他某个学员不工作而导致报告无法提交到主管手中,我们称这种学员为不可靠的.而不受某个学员不工作而影响到报告提交的就是可靠学员.问题就是找出可靠学员的数量. 输