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建图


  • 相关阅读:
    sass的安装
    git上传项目到github教程
    v-if 和v-show的区别
    es5实现数组去重
    原生js实现选中所有的checkbox
    拨打手机号
    H5页面打开小程序
    h5 网页 直接唤起淘宝app,并跳转到对应商品页面
    webstorm配置git
    elementUi 日历添加可选区间(只能选择一个月的时间段)
  • 原文地址:https://www.cnblogs.com/qq-1585047819/p/11551896.html
Copyright © 2011-2022 走看看