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

    描述

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

    输入格式

    第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条有向边。

    输出格式

    共N行,表示每个点能够到达的点的数量。

    样例输入

    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
    

    分析:拓扑排序,为了计数方便避免重复记录后续,使用bitset来储存n个结点对于n个结点的可达情况,二进制直接通过或运算即可从后向前扫描拓扑序列。

    #define MAX 30001
    int head[MAX],nxt[MAX],ver[MAX],deg[MAX];
    int a[MAX];
    int n,m;
    int cnt = 0,tot=0;
    bitset<30001> s[MAX];
    void add(int x,int y)
    {
    	ver[++tot] = y;
    	nxt[tot] = head[x];
    	head[x] = tot;
    	deg[y]++;
    }
    void topsort()
    {
    	queue<int>q;
    	for(int i= 1;i<=n;i++)
    		if(deg[i]==0)
    			q.push(i);
    	while(q.size())
    	{
    		int x = q.front();
    		q.pop();
    		a[++cnt] = x;
    		for(int i=head[x];i;i=nxt[i])
    		{
    			int y = ver[i];
    			if(--deg[y]==0)
    				q.push(y);
    		}
    	}
    }
    void sol()
    {
    	for(int i=cnt;i;i--)
    	{
    		int x = a[i];
    		s[x][x] = 1;
    		for(int j=head[x];j;j=nxt[j])
    		{
    			int y=ver[j];
    			s[x]|=s[y];
    		}
    	}
    }
    int main() 
    {
      	cin>>n>>m;
      	for(int i=0;i<m;i++)
      	{
      		int x,y;
      		scanf("%d%d",&x,&y);
      		add(x,y);
      	}
      	topsort();
      	sol();
      	for(int i=1;i<=n;i++)
      	{
      		printf("%d
    ",s[i].count());
      	}
        return 0;
    }
    
  • 相关阅读:
    List某字段相同时将其他字段数据相加
    【转】常见面试之机器学习算法思想简单梳理
    【转】R语言知识体系概览
    【转】聊聊HTTPS和SSL/TLS协议
    面试总结【1】
    【转】学习Python的19个资源
    【转】机器学习资料汇总
    Python小爬虫
    【转】python操作mysql数据库
    SQL语法
  • 原文地址:https://www.cnblogs.com/1625--H/p/9484073.html
Copyright © 2011-2022 走看看