zoukankan      html  css  js  c++  java
  • AcWing P164 可达性统计 题解

    Analysis

    这道题我一开始想到的是传递闭包,但是时间复杂度是n³,也开不下30000*30000的数组,所以我想到了拓扑+状态压缩(bitset),从后往前找,把能到达的点能到哪里用位运算赋到上一个中,最后调用.count()输出就好了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<bitset>
     7 #define maxn 30010
     8 using namespace std;
     9 inline int read() 
    10 {
    11     int x=0;
    12     bool f=1;
    13     char c=getchar();
    14     for(; !isdigit(c); c=getchar()) if(c=='-') f=0;
    15     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0';
    16     if(f) return x;
    17     return 0-x;
    18 }
    19 inline void write(int x)
    20 {
    21     if(x<0){putchar('-');x=-x;}
    22     if(x>9)write(x/10);
    23     putchar(x%10+'0');
    24 }
    25 queue<int> q;
    26 bitset<maxn> s[maxn];
    27 int n,m,cnt,num;
    28 int head[2*maxn],rd[maxn],path[maxn];
    29 struct node
    30 {
    31     int v,nex;
    32 }edge[2*maxn];
    33 inline void add(int u,int v)
    34 {
    35     cnt++;
    36     edge[cnt].v=v;
    37     edge[cnt].nex=head[u];
    38     head[u]=cnt;
    39 }
    40 inline void topo()
    41 {
    42     for(int i=1;i<=n;i++)
    43     {
    44         if(rd[i]==0)q.push(i);
    45     }
    46     while(!q.empty())
    47     {
    48         int t=q.front();
    49         q.pop();
    50         num++;
    51         path[num]=t;
    52         for(int i=head[t];i;i=edge[i].nex)
    53         {
    54             int to=edge[i].v;
    55             rd[to]--;
    56             if(rd[to]==0)q.push(to);
    57         }
    58     }
    59 }
    60 int main()
    61 {
    62     n=read();m=read();
    63     for(int i=1;i<=m;i++)
    64     {
    65         int x,y;
    66         x=read();y=read();
    67         add(x,y);
    68         rd[y]++;
    69     }
    70     topo();
    71     for(int i=num;i>=1;i--)
    72     {
    73         int x=path[i];
    74         s[x][x]=1;
    75         for(int j=head[x];j;j=edge[j].nex)
    76         {
    77             int to=edge[j].v;
    78             s[x]|=s[to];
    79         }
    80     }
    81     for(int i=1;i<=n;i++)
    82     {
    83         write(s[i].count());
    84         printf("
    ");
    85     }
    86     return 0;
    87 }
    请各位大佬斧正(反正我不认识斧正是什么意思)
  • 相关阅读:
    (LeetCode 72)Edit Distance
    (LeetCode 53)Maximum Subarray
    (LeetCode 64)Minimum Path Sum
    (算法)关于随机数的生成
    (笔试题)数组A中任意两个相邻元素大小相差1,在其中查找某个数。
    (笔试题)分椰子
    (笔试题)和0交换的排序
    (笔试题)合法字符串
    (笔试题)被3和5整除的数的和
    (笔试题)程序运行时间
  • 原文地址:https://www.cnblogs.com/handsome-zyc/p/11268250.html
Copyright © 2011-2022 走看看