欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-19 10:21:34
...

给定一张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

 

 一开始以为是个水题,想都没想dfs就敲起来了。

结果TLE,y总说还会爆内存。。。

对于时间复杂度和空间复杂度还是不能很好的估量。

注意开数组变量时,大一点点就行了。小心爆内存!

因为是有向无环图,所以可以拓扑排序,拓扑排序完之后有一个很好的性质,就是所有的有向边都是从前指向后。

设f[x]为x点所能到达的点的集合,集合关系的表示可以用位运算来表示,bitset很好用。

topsort+ 状态压缩

AC Code:

#include<bits/stdc++.h>
#define LL long long
#define ULL  unsigned  long long
#define maxn (LL)1e5
#define INF 0x3f3f3f3f
#define inf 0x7fffffff
#define PI  acos(-1.0)
#define pb push_back
#define re register
const double eps = 0.0000001;
using namespace std;
typedef pair<LL,LL> pii;
inline LL sgn(double x) {
    return (x > eps) - (x < -eps);
}
const int N = 30010;
using namespace std;
struct Edge
{
    int next;
    int to;
}edge[N];
int head[N],tot;
int deg[N];
int ans[N];
 int n,m;bitset<N> f[N];
 int k = 1;
inline void add(int from,int to)
{
    edge[++tot].next = head[from];
    edge[tot].to = to;
    deg[to]++;
    head[from] = tot;
}
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();
        ans[k++] = x;
        Q.pop();
        for(int i = head[x];~i;i = edge[i].next)
        {
            int y = edge[i].to;
            if(--deg[y]==0) Q.push(y);
        }
    }
}
int main()
{
    //freopen("input.txt","r",stdin);
  memset(head,-1,sizeof(head));
  cin>>n>>m;
   memset(head,-1,sizeof(head));
   for(int i = 1;i<=m;++i)
   {
       int f,t;
       cin>>f>>t;
       add(f,t);

   }
   topsort();

  for(int i = k-1;i>=1;i--)//倒着推集合关系
  {
      int x = ans[i];
      f[x][x] = 1;
      for(int j = head[x];~j;j = edge[j].next)
      {
          int y = edge[j].to;
          f[x] |= f[y];
      }
  }
  for(int i = 1;i<=n;++i)
  {
      cout<<f[i].count()<<endl;
  }


}