hdu5195 二分+线段树+拓扑序

这题说的给了n个点m条边要求保证是一个有向无环图,可以删除至多k条边使得这个图的拓扑序的字典序最大,我们知道如果我们要排一个点的时候一定要考虑比他大的点是否可以、通过拆边马上拆出来,如果可以拆当然是拆,肯定保证字典序最大,如果不能拆,就不拆留着以后拆,当初这个比他大的点度数小于k的,最大是多少,这个方法我一直想不出,后来看了题解,二分加线段树,可以做到,线段树维护每个点的d[i],然后通过二分找出小于k的最大点是多少。

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <string.h>
  4 #include <vector>
  5 #include <cstdio>
  6 #include<queue>
  7 using namespace std;
  8 const int maxn =100005;
  9 struct Edge{
 10    int u,v;
 11    Edge(int uu=0, int vv=0){
 12        u= uu; v =vv;
 13    }
 14 };
 15 vector<Edge> E;
 16 vector<int> G[maxn],REG[maxn];
 17 void add_edg(int u, int v){
 18     E.push_back(Edge(u,v));
 19     G[u].push_back(E.size()-1);
 20     REG[v].push_back(E.size()-1);
 21 }
 22 int ind[maxn];
 23 int cL, cR,cans;
 24 struct Itree{
 25     int id[maxn*4];
 26     void build(int O, int L, int R){
 27         if(L==R){
 28               id[O] = ind[L] ; return ;
 29         }
 30         int mid = ( L + R ) >> 1 ;
 31         build(O*2,L,mid);
 32         build(O*2+1,mid+1,R);
 33         id[O]=min(id[O*2],id[O*2+1]);
 34     }
 35     void update(int o, int L, int R){
 36         if(  L == R ){
 37               id[o] = cans;  return ;
 38         }
 39         int mid=(L+R)>>1;
 40         if(cL<=mid){
 41              update(o*2,L,mid);
 42         }else update(o*2+1,mid+1,R);
 43         id[o]=min(id[o*2],id[o*2+1]);
 44     }
 45     void query(int o , int L, int R){
 46         if(cL<=L && cR>=R){
 47              cans =min(cans,id[o]);return ;
 48         }
 49         int mid = (L+R)>>1;
 50         if(cL <= mid) query(o*2,L,mid);
 51         if(cR>mid) query(o*2+1,mid+1,R);
 52     }
 53 }T;
 54 bool use[maxn];
 55 void init(int n){
 56     for(int i=0; i<n; i++){
 57          G[i].clear();
 58          REG[i].clear();
 59     }
 60     E.clear();
 61     memset(ind,0,sizeof(ind));
 62     memset(use,true,sizeof(use));
 63 }
 64 int jud(int k, int n){
 65    int L=1,R=n,ans=-1;
 66    while(L<=R){
 67         int mid = (L+R)>>1;
 68         cans = k+1;
 69         cL=mid; cR=R;
 70         T.query(1,1,n);
 71         if(cans<=k){
 72              ans=mid; L=mid+1;
 73         }
 74         else R=mid-1;
 75    }
 76    return ans;
 77 }
 78 priority_queue<int> Q;
 79 void solve1(int nk,int k,int n){
 80
 81      for(int i=0; i<REG[nk].size(); i++){
 82           use[ REG[nk][i] ] = false;
 83      }
 84      cans = k+1;
 85      cL=cR=nk;
 86      T.update(1,1,n);
 87 }
 88 void solve2(int nk,int k,int n){
 89     for(int i=0; i<G[nk].size(); i++){
 90         int numedg = G[nk][i];
 91         if(use[numedg]){
 92              use[numedg]=false;
 93              Edge q = E[numedg];
 94              ind[q.v]--;
 95              if(ind[q.v]==0){
 96                 Q.push(q.v); ind[q.v]=k+1;
 97              }
 98              cL = cR = q.v;
 99              cans =ind[q.v];
100              T.update(1,1,n);
101         }
102     }
103 }
104 int ans[maxn];
105 int main()
106 {
107      int n,m,k;
108
109      while(scanf("%d%d%d",&n,&m,&k)==3){
110          init(n);
111          for(int i=0; i<m; i++){
112              int u,v;
113              scanf("%d%d",&u,&v);
114              add_edg(u,v);
115              ind[v]++;
116          }
117          while(!Q.empty())Q.pop();
118          for(int i =1; i<=n; i++){
119              if(ind[i]==0){
120                  Q.push(i);
121                  ind[i]=k+1;
122              }
123          }
124          T.build(1,1,n);
125          int st=0;
126          while(!Q.empty()){
127              int top = Q.top();
128              int nk = jud(k,n);
129              if(nk>top){
130                  k-=ind[nk];
131                  solve1(nk,k,n);
132                  Q.push(nk);
133              }else{
134                  Q.pop();
135                  ans[st++]=top;
136                  solve2(top,k,n);
137              }
138          }
139          for(int i=0; i<n-1; i++) printf("%d ",ans[i]);
140          printf("%d\n",ans[n-1]);
141      }
142
143     return 0;
144 }
时间: 2024-08-29 12:12:33

hdu5195 二分+线段树+拓扑序的相关文章

bzoj 3832: [Poi2014]Rally(线段树+拓扑排序)

3832: [Poi2014]Rally Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special Judge Submit: 113  Solved: 56 [Submit][Status][Discuss] Description An annual bicycle rally will soon begin in Byteburg. The bikers of Byteburg are natural long distance cyclis

Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB 总提交次数:196   AC次数:65   平均分:58.62 将本题分享到: 查看未格式化的试题   提交   试题讨论 试题来源 2013中国国家集训队第二次作业 问题描述 给定一棵N个节点的树,每个点有一个权值,有M个询问(a,b,c)若a 为1,回答b到c路径上的最小权值,若a为2,回答b到c路径上的最大权值,若a为3,回答b到c路径上的所有权值的

【BZOJ-3110】K大数查询 整体二分 + 线段树

3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6265  Solved: 2060[Submit][Status][Discuss] Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M接下来M行,每行形如1 a

Codeforces 384E 线段树+dfs序

题目链接:点击打开链接 题意: 给定n个点,m个询问的无向树(1为根) 下面n个数表示每个点的权值 下面n-1行给出树 操作1:x点权值+v, x的第 i & 1 的儿子-v, 第 !(i&1) 的儿子+v 操作2:询问x点权值 dfs把树转成序列 根据深度把点分成2组 分别用线段树维护.. 然后Y一下 #include<stdio.h> #include<string.h> #include<iostream> #include<algorith

线段树+dfs序(Apple Tree )(Assign the task )

线段树+dfs序 给定一棵n个节点的树,m次查询,每次查询需要求出某个节点深度为h的所有子节点. 作为预处理,首先将树的所有节点按深度保存起来,每个深度的所有节点用一个线性结构保存,每个深度的节点相对顺序要和前序遍历一致. 然后从树的根节点进行dfs,对于每个节点记录两个信息,一个是dfs进入该节点的时间戳in[id],另一个是dfs离开该节点的时间戳out[id]. 最后对于每次查询,求节点v在深度h的所有子节点,只需将深度为h并且dfs进入时间戳在in[v]和out[v]之间的所有节点都求出

HDU5195 线段树+拓扑

DZY Loves Topological Sorting Problem Description A topological sort or topological ordering of a directed graph is a linear ordering of its vertices such that for every directed edge (u→v) from vertex u to vertex v , u comes before v in the ordering

hdu5195 DZY Loves Topological Sorting 线段树+拓扑排序

要求在一个DAG中删去不多于k条边,使得拓扑序的字典序最大. 贪心策略:每次删去入度小于res的,序号尽量大的点的入边. 需要用线段树维护区间最小值. 代码: #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<vector> using name

HDU5638 / BestCoder Round #74 (div.1) 1003 Toposort 线段树+拓扑排序

Toposort 问题描述 给出nn个点mm条边的有向无环图. 要求删掉恰好kk条边使得字典序最小的拓扑序列尽可能小. 输入描述 输入包含多组数据. 第一行有一个整数TT, 表示测试数据组数. 对于每组数据: 第一行包含3个整数nn, mm和kk (1 \le n \le 100000, 0 \le k \le m \le 200000)(1≤n≤100000,0≤k≤m≤200000), 表示图中结点数目, 图中边的数目以及要删的边数. 接下来mm行, 每行包含两个整数u_iu?i?? and

hdu 5195 DZY Loves Topological Sorting 线段树+拓扑排序

DZY Loves Topological Sorting Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5195 Description A topological sort or topological ordering of a directed graph is a linear ordering of its vertices such that for ev