可达?

可达?

题目描述

小明有一张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

题解

对于节点x和y如果x可以到达y那么x所能到达的点为y所能到达的点加上x能到达的其他点能到达的点数,可见这是一个递推问题,我们从最末的点也就是出度为0的点开始就可以递推出所有点能到达的点的个数,所以问题变成了,找到这个递推顺序,从上面的描述可见,这个顺序就是拓扑排序序列的倒序,所以我们对原图做拓扑排序后,递推得出结果即可。当我们观察样例输出可以发现,这个题的输入存在重复,所以如果我们直接计算会出现重复,所以这题用bitset来维护答案。

/**********************************************************
* @Author: 			   Maple
* @Date:   			   2020-02-29 13:50:45
* @Last Modified by:   Maple
* @Last Modified time: 2020-02-29 14:25:15
* @Remark: 
**********************************************************/
#include <bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define CSE(x,y) memset(x,y,sizeof(x))
#define INF 0x3f3f3f3f
#define Abs(x) (x>=0?x:(-x))
#define FAST ios::sync_with_stdio(false);cin.tie(0);
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll , ll> pll;

const int maxn=33333;
int n,m,indegree[maxn],ans[maxn];
std::vector<int> graph[maxn];
bitset<maxn> bit[maxn];
stack<int> box;

void topsort(){//拓扑排序
	queue<int> mid;
	for(int i=1;i<=n;i++){
		if(indegree[i]==0)
			mid.push(i);
	}
	while(!mid.empty()){
		int now=mid.front();
		mid.pop();box.push(now);
		for(auto k:graph[now]){
			indegree[k]--;
			if(indegree[k]==0)
				mid.push(k);
		}
	}
	return;
}

void count(){//递推统计结果
	while(!box.empty()){
		int x=box.top();
		box.pop();
		bit[x][x]=1;
		for(auto k:graph[x]){
			bit[x]=bit[x]|bit[k];
		}
	}
	return;
}

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	#endif
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		graph[x].push_back(y);
		indegree[y]++;
	}
	topsort();
	count();
	for(int i=1;i<=n;i++){
		printf("%d
",bit[i].count());
	}
	return 0;
}
原文地址:https://www.cnblogs.com/LeafLove/p/12382832.html