zoukankan      html  css  js  c++  java
  • 164. 可达性统计

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

    输入格式

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

    输出格式

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

    数据范围

    1N,M300001≤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

    题意分析:
    题目已经说明白,给我们的是DAG(有向无环图)。既然是DAG,可以很容易的联想到拓扑排序。题目让我们统计每个点出发能到达的点的数量,我们可以先模拟一下样例,如下图(只例举出1,2,3三个点)。

    题解:
    综上所述,设从点 x 出发能够到达的点构成的集合是 f(x),从点 x 出发能够到达的点,是从 x 的各个后继节点 y 出发能够到达的点的并集,再加上点 x 自身 。
    f(2) = f(3) ∪ f(5) ∪ f(10) = …
    先按照拓扑排序算法求出拓扑序,然后按照拓扑序的倒叙进行计算------因为在拓扑序中,任意一条边 (x , y),x 都排在 y 之前。
    关于状态压缩 bitset容器:
    转载:https://oi-wiki.org/ds/stl/bitset/


    介绍¶
    std :: bitset 是标准库中的一个固定大小序列,其储存的数据只包含 0/1
    众所周知,由于内存地址是按字节即 byte 寻址,而非比特 bit ,
    我们一个 bool 类型的变量,虽然只能表示 0/1 , 但是也占了 1byte 的内存
    bitset 就是通过固定的优化,使得一个字节的八个比特能分别储存 8 位的 0/1
    对于一个 4 字节的 int 变量,在只存 0/1 的意义下, bitset 占用空间只是其
    在某些情况下通过 bitset 可以使你的复杂度除以 32
    当然, vector 的一个特化 vector<bool> 的储存方式同 bitset 一样,区别在于其支持动态开空间,
    bitset 则和我们一般的静态数组一样,是在编译时就开好了的。
    那么为什么要用 bitset 而非 vector<bool> ?
    通过以下的介绍,你可以更加详细的看到 bitset 具备的方便操作
    #include <bitset> // 包含 bitset 的头文件


    运算符¶


    operator[] : 访问其特定的一位


    operator ==/!= : 比较两个 bitset 内容是否完全一样


    operator &=/|=/^=/~ : 进行按位与/或/异或/取反操作


    operator <</>>/<<=/>>= : 进行二进制左移/右移


    operator <</>> : 流运算符,这意味着你可以通过 cin/cout 进行输入输出


    vector<bool> 只具有前两项
    成员函数¶

    test() : 它和 vector 中的 at() 的作用是一样的,和 [] 运算符的区别就是越界检查
    count() : 返回 true 的数量
    set() : 将整个 bitset 设置成 true , 你也可以传入参数使其设置成你的参数
    reset() : 将整个 bitset 设置成 false
    flip() : 翻转该位 (0 变 1,1 变 0), 相当于逻辑非/异或 1
    to_string() : 返回转换成的字符串表达
    to_ulong() : 返回转换成的 unsigned long 表达 ( long 在 NT 及 32 位 POSIX 系统下与 int 一样,在 64 位 POSIX 下与 long long 一样)
    to_ullong() C++11, 返回转换成的 unsigned long long 表达

    这些 vector<bool> 基本都没有
    作用¶
    一般来讲,我们可以用 bitset 优化一些可行性 DP, 或者线筛素数 ( notprime 这种 bool 数组可以用 bitset 开到 之类的)
    它最主要的作用还是压掉了内存带来的时间优化, 的常数优化已经可以是复杂度级别的优化了,比如一个 的 算法, 显然很卡,在常数大一点的情况下必然卡不过去,O(松)不能算!, 这时候如果我们某一维除以 32, 则可以比较保险的过了这道题
    其实 bitset 不光是一个容器,更是一种思想,我们可以通过手写的方式,来把 long long 什么的压成每 bit 表示一个信息,用 STL 的原因更多是因为它的运算符方便

     1 #include <iostream>
     2 #include <cstring>
     3 #include <bitset>
     4 #include <algorithm>
     5 #include <queue>
     6 using namespace std;
     7 int n,m;
     8 const int maxn=3e4+5;
     9 bitset<maxn> f[maxn];
    10 int h[maxn],e[maxn],ne[maxn],idx;
    11 int seq[maxn],in[maxn];
    12 
    13 void add(int a,int b){
    14     e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    15 }
    16 
    17 void topsort(){
    18     queue<int> que;
    19     for(int i=1;i<=n;i++){
    20         if(in[i]==0) que.push(i);
    21     }
    22     int jishu=0;
    23     while(!que.empty()){
    24         int top=que.front();
    25         que.pop();
    26         seq[jishu++]=top;
    27         for(int j=h[top];~j;j=ne[j]){
    28             int ee=e[j];   //与其相连的那条边
    29             if(--in[ee]==0) que.push(ee);
    30         }
    31     }
    32 }
    33 
    34 int main(){
    35     cin>>n>>m;
    36     memset(h,-1,sizeof(h));
    37     for(int i=1;i<=m;i++){
    38         int d1,d2;
    39         cin>>d1>>d2;
    40         add(d1,d2);
    41         in[d2]++;
    42     }
    43     topsort();
    44     for(int i=n-1;i>=0;i--){
    45         int j=seq[i];
    46         f[j][j]=1;
    47         for(int k=h[j];~k;k=ne[k]){
    48             f[j]|=f[e[k]];
    49         }
    50     }
    51     for(int i=1;i<=n;i++){
    52         cout << f[i].count() << endl;
    53     }
    54     return 0;
    55 }
    邻接表建图
      1 #include <iostream>
      2 #include <cstring>
      3 #include <bitset>
      4 #include <algorithm>
      5 #include <queue>
      6 using namespace std;
      7 int n,m;
      8 const int maxn=3e4+5;
      9 bitset<maxn> f[maxn];
     10 int h[maxn],e[maxn],ne[maxn],idx;
     11 int seq[maxn],in[maxn];
     12 
     13 void add(int a,int b){
     14     e[idx]=b,ne[idx]=h[a],h[a]=idx++;
     15 }
     16 
     17 void topsort(){
     18     queue<int> que;
     19     for(int i=1;i<=n;i++){
     20         if(in[i]==0) que.push(i);
     21     }
     22     int jishu=0;
     23     while(!que.empty()){
     24         int top=que.front();
     25         que.pop();
     26         seq[jishu++]=top;
     27         for(int j=h[top];~j;j=ne[j]){
     28             int ee=e[j];   //与其相连的那条边
     29             if(--in[ee]==0) que.push(ee);
     30         }
     31     }
     32 }
     33 
     34 int main(){
     35     cin>>n>>m;
     36     memset(h,-1,sizeof(h));
     37     for(int i=1;i<=m;i++){
     38         int d1,d2;
     39         cin>>d1>>d2;
     40         add(d1,d2);
     41         in[d2]++;
     42     }
     43     topsort();
     44     for(int i=n-1;i>=0;i--){
     45         int j=seq[i];
     46         f[j][j]=1;
     47         for(int k=h[j];~k;k=ne[k]){
     48             f[j]|=f[e[k]];
     49         }
     50     }
     51     for(int i=1;i<=n;i++){
     52         cout << f[i].count() << endl;
     53     }
     54     return 0;
     55 }
     56 
     57 
     58 
     59 #include <iostream>
     60 #include <cstring>
     61 #include <bitset>
     62 #include <algorithm>
     63 #include <queue>
     64 using namespace std;
     65 int n,m;
     66 const int maxn=3e4+5;
     67 bitset<maxn> f[maxn];
     68 vector<int> G[maxn];
     69 int seq[maxn],in[maxn];
     70 
     71 void topsort(){
     72     queue<int> que;
     73     for(int i=1;i<=n;i++){
     74         if(in[i]==0) que.push(i);
     75     }
     76     int jishu=0;
     77     while(!que.empty()){
     78         int top=que.front();
     79         que.pop();
     80         seq[jishu++]=top;
     81         for(auto X:G[top]){
     82             if(--in[X]==0) que.push(X);
     83         }
     84     }
     85 }
     86 
     87 int main(){
     88     cin>>n>>m;
     89     for(int i=1;i<=m;i++){
     90         int d1,d2;
     91         cin>>d1>>d2;
     92         G[d1].push_back(d2);
     93         in[d2]++;
     94     }
     95     topsort();
     96     for(int i=n-1;i>=0;i--){
     97         int j=seq[i];
     98         f[j][j]=1;
     99         for(auto X:G[j]){
    100             f[j]|=f[X];
    101         }
    102     }
    103     for(int i=1;i<=n;i++){
    104         cout << f[i].count() << endl;
    105     }
    106     return 0;
    107 
    108 
    109 }
    vector建图


  • 相关阅读:
    iOS 面试题搜集
    iOS 常用第三方类库、完整APP示例
    iOS 键盘遮挡输入 解决办法
    iOS UIColor RGB HEX
    iOS APP性能优化
    iOS Swift 数组 交换元素的两种方法
    iOS CoreData primitive accessor
    iOS Start developing ios apps (OC) pdf
    iOS 传值方式
    iOS IB_DESIGNABLE IBInspectable @IBDesignable @IBInspectable 加速UI开发
  • 原文地址:https://www.cnblogs.com/qq-1585047819/p/11551896.html
Copyright © 2011-2022 走看看