zoukankan      html  css  js  c++  java
  • 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
    ",ans[n-1]);
    141      }
    142 
    143     return 0;
    144 }
  • 相关阅读:
    HTML5超科幻个人主页
    用Java开发50个棋类游戏
    Android 4.2 project导入 5.0 SDK Eclipse 开发环境出现的问题总结
    蓝桥杯 地宫寻宝 带缓存的DFS
    HDU2577 How to Type【DP】
    Entity Framework 学习总结之一:ADO.NET 实体框架概述
    ASP.NET MVC4中调用WEB API的四个方法
    ASP.NET MVC Web API 学习笔记---第一个Web API程序
    ASP.Net MVC开发基础学习笔记(1):走向MVC模式
    MVC4笔记 Area区域
  • 原文地址:https://www.cnblogs.com/Opaser/p/4375552.html
Copyright © 2011-2022 走看看