可达?
题目描述
小明有一张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;
}