zoukankan      html  css  js  c++  java
  • 可达性统计(拓扑排序 + 状态压缩)

    可达性统计 题目地址(牛客)

    一道比较经典的拓扑排序题

    题目描述

    给定一张(N)个点(M)条边的有向无环图,分别统计从每个点出发能够到达的点的数量。(N,M≤30000)

    题解

    设从点 u 出发能够到达的点构成的集合是 f(u),从点 u 出发能够到达的点,是从 u 的各个后继节点 v 出发能够到达的点的并集,再加上点 u 自身。先按照拓扑排序算法求出拓扑序,然后按照拓扑序的倒叙进行计算------因为在拓扑序中,任意一条边 (u ,v),u 都排在 v 之前。倒序处理即可。

    Code

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<bitset>
    #include<cmath>
    #include<queue>
    #define N 30007
    using namespace std;
    inline int read() {
    	int x=0,f=1; char ch=getchar();
    	while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    	while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
    	return x * f;
    }
    int n,m,cnt,tot;
    int head[N],du[N],tp[N];	//tp拓扑序数组 
    struct Edge {
    	int next,to;
    }edge[N<<1];
    inline void add(int u,int v) {
    	edge[++cnt].next = head[u];
    	edge[cnt].to = v;
    	head[u] = cnt;
    }
    void topo() {
    	queue<int> q;
    	for(int i=1;i<=n;++i)
    		if(!du[i]) q.push(i);
    	while(!q.empty()) {
    		int u = q.front(); q.pop();
    		tp[++tot] = u;
    		for(int i=head[u];i;i=edge[i].next) {
    			int v = edge[i].to;
    			du[v]--; if(!du[v]) q.push(v);
    		}
    	}
    }
    int main()
    {
    	n = read() ,m = read();
    	for(int i=1,u,v;i<=m;++i) {
    		u = read() ,v = read();
    		add(u,v); du[v]++;
    	}
    	topo();
    	bitset<N> f[N];
    	for(int i=cnt;i>=1;--i) {
    		int u = tp[i];
    		f[u][u] = 1;
    		for(int j=head[u];j;j=edge[j].next) {
    			int v = edge[j].to;
    			f[u] |= f[v];	//只要有就继承一下儿子 
    		}
    	}
    	for(int i=1;i<=n;++i)
    		printf("%d
    ",f[i].count());
    	return 0;
    }
    
  • 相关阅读:
    terminal
    变量提升、函数提升
    ssh传输文件
    mocha测试框架
    npm-run 自动化
    webpack
    浅析babel
    构建工具gulp
    C++中TRACE宏及assert()函数的使用
    memcpy函数-C语言
  • 原文地址:https://www.cnblogs.com/BaseAI/p/11364491.html
Copyright © 2011-2022 走看看