• hdu 5195 线段树


    题目描述:给定一个DAG,求出允许移除最多K条边后的字典序最大的拓扑序列。

    思路:线段树,每次找入度不超过K的最大编号的顶点,将此顶点从图中移除,重复操作n次即可得到结果。

    吐槽:当时打BC的时候写出了一个贪心+拓扑排序的复杂度为O(n)的错误代码(当时还没有意识到是错误代码),交到hdu oj上居然给过了,后来上西方文化的时候和csc得瑟,说那个题我300+ms就给过了,在best solutions里面Rank 1,复杂度是O(n)的,然后和csc说了我的想法以后才发现这思路TM根本就不对啊,hdu的数据出水了!后来才改用线段树写!

    附超快-错误-可AC代码如下:

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <cstdio>
     5 #include <queue>
     6 using namespace std;
     7 
     8 priority_queue<int> q;
     9 const int N = 111111;
    10 bool mark[N];
    11 int in[N];
    12 int head[N];
    13 int ans[N], index;
    14 int n, m, k, e;
    15 
    16 struct Edge
    17 {
    18     int v, next;
    19 } edge[N];
    20 
    21 void addEdge( int u, int v )
    22 {
    23     edge[e].v = v;
    24     edge[e].next = head[u];
    25     head[u] = e;
    26     e++;
    27 }
    28 
    29 void init()
    30 {
    31     e = 0;
    32     index = 0;
    33     memset( in, 0, sizeof(in) );
    34     memset( head, -1, sizeof(head) );
    35     memset( mark, false, sizeof(mark) );
    36     while ( !q.empty() )
    37     {
    38         q.pop();
    39     }
    40 }
    41 
    42 int main ()
    43 {
    44     while ( scanf("%d%d%d", &n, &m, &k) != EOF )
    45     {
    46         init();
    47         for ( int i = 1; i <= m; i++ )
    48         {
    49             int u, v;
    50             scanf("%d%d", &u, &v);
    51             in[v]++;
    52             addEdge( u, v );
    53         }
    54         for ( int i = n; i > 0 && k > 0; i-- )
    55         {
    56             if ( k >= in[i] )
    57             {
    58                 k -= in[i];
    59                 in[i] = 0;
    60                 ans[index++] = i;
    61                 for ( int u = head[i]; u != -1; u = edge[u].next )
    62                 {
    63                     int v = edge[u].v;
    64                     in[v]--;
    65                 }
    66                 mark[i] = true;                
    67             }
    68         }
    69         for ( int i = 1; i <= n; i++ )
    70         {
    71             if ( in[i] == 0 && mark[i] == false )
    72             {
    73                 q.push(i);
    74             }
    75         }        
    76         while ( !q.empty() )
    77         {
    78             int tmp = q.top();
    79             q.pop();
    80             ans[index++] = tmp;
    81             for ( int u = head[tmp]; u != -1; u = edge[u].next )
    82             {
    83                 int v = edge[u].v;
    84                 in[v]--;
    85                 if ( in[v] == 0 )
    86                 {
    87                     q.push(v);
    88                 }
    89             }
    90         }
    91         for ( int i = 0; i < index - 1; i++ )
    92         {
    93             printf("%d ", ans[i]);
    94         }
    95         printf("%d
    ", ans[index - 1]);
    96     }
    97     return 0;
    98 }
    View Code

    附正确代码如下:

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 using namespace std;
      5 
      6 const int N = 100001;
      7 const int INF = 9999999;
      8 int in[N];
      9 int head[N];
     10 int n, m, k, e;
     11 
     12 int min( int a, int b )
     13 {
     14     return a < b ? a : b;
     15 }
     16 
     17 struct Edge 
     18 {
     19     int v, next;
     20 } edge[N];
     21 
     22 void addEdge( int u, int v )
     23 {
     24     edge[e].v = v;
     25     edge[e].next = head[u];
     26     head[u] = e++;
     27 }
     28 
     29 struct Node 
     30 {
     31     int l, r, in;
     32 } node[N * 3];
     33 
     34 void build( int i, int l, int r )
     35 {
     36     node[i].l = l, node[i].r = r;
     37     if ( l == r )
     38     {
     39         node[i].in = in[l];
     40         return ;
     41     }
     42     int mid = l + r >> 1;
     43     build( i << 1, l, mid );
     44     build( i << 1 | 1, mid + 1, r );
     45     node[i].in = min( node[i << 1].in, node[i << 1 | 1].in );    
     46     return ;
     47 }
     48 
     49 void update( int i, int pos )
     50 {
     51     if ( node[i].l == node[i].r )
     52     {
     53         node[i].in = in[pos];
     54         return ;
     55     }
     56     int mid = node[i].l + node[i].r >> 1;
     57     if ( pos <= mid )
     58     {
     59         update( i << 1, pos );
     60     }
     61     else
     62     {
     63         update( i << 1 | 1, pos );
     64     }
     65     node[i].in = min( node[i << 1].in, node[i << 1 | 1].in );
     66     return ;
     67 }
     68 
     69 int query( int i )
     70 {
     71     while ( node[i].l != node[i].r )
     72     {
     73         if ( k >= node[i << 1 | 1].in )
     74         {
     75             i = i << 1 | 1;
     76         }
     77         else
     78         {
     79             i = i << 1;
     80         }
     81     }
     82     return node[i].l;
     83 }
     84 
     85 void init()
     86 {
     87     e = 0;
     88     memset( head, -1, sizeof(head) );
     89     memset( in, 0, sizeof(in) );
     90 }
     91 
     92 int main ()
     93 {
     94     while ( scanf("%d%d%d", &n, &m, &k) != EOF )
     95     {
     96         init();
     97         while ( m-- )
     98         {
     99             int u, v;
    100             scanf("%d%d", &u, &v);
    101             addEdge( u, v );
    102             in[v]++;
    103         }
    104         build( 1, 1, n );
    105         for ( int i = 0; i < n - 1; i++ )
    106         {
    107             int t = query(1);
    108             printf("%d", t);
    109             if ( i < n - 1 ) putchar(' ');
    110             k -= in[t];
    111             in[t] = INF;
    112             update( 1, t );
    113             for ( int u = head[t]; u != -1; u = edge[u].next )
    114             {
    115                 int v = edge[u].v;
    116                 if ( in[v] == INF ) continue;
    117                 in[v]--;
    118                 update( 1, v );
    119             }
    120         }
    121         printf("%d
    ", query(1));
    122     }
    123     return 0;
    124 }

    说明:用g++交不一定能过,最好挑个交题的人比较少的时候,c++妥妥的。

  • 相关阅读:
    整站爬虫命令
    小故事集锦
    中国最经典广告语大全
    常用的正则表达式
    特殊成员方法
    使用super函数----增量重写普通方法和构造方法
    重写普通方法和构造方法------原类的方法会被覆盖
    Python的数据类型与数据结构
    类和对象
    生产者-消费者问题与quene模块
  • 原文地址:https://www.cnblogs.com/huoxiayu/p/4391303.html
Copyright © 2020-2023  润新知