zoukankan      html  css  js  c++  java
  • ZROI2018提高day9t1

    传送门

    分析

    我们首先想到的自然是根据大小关系建图,在这之后我们跑一遍拓扑排序

    但是由于l和r的限制关系我们需要对传统的拓扑排序做一些改变

    我们考虑将所有入度为0且现在的拓扑序号已经大于等于l的点放入一个优先队列,这个优先队列以r为关键字从小到大排序,这样我们就可以保证r小的点被排在前面

    但是我们发现暴力判断l是否合法是行不通的,于是我们考虑再建一个优先队列,将所有入度为0的点以l为关键字从小到大排序,每次当队首l大于等于当前序号则弹出这个点,将这个点加入到r的那个优先队列中,这样我们就可以保证每个点最多在这个优先队列中进一次出一次

    但是我们还要考虑一种情况,如果对于点1和点2,1的值小于2的值但是l[1]<l[2]且r[1]>r[2]则可能1的取值在区间(r[1],r[2]),那这种情况肯定是不合法的,所以我们要在求拓扑序等一众操作之前先对图进行一遍dfs来判断这个图是不是一个DAG并将点i的r值更新为min(l[i],l[I's son]),注意这个值是从后往前一一更新的,来保证对于点i,所有它能到达的点跟i的lr关系均合法

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    int n,m,le[300100],ri[300100],T,d[300100],id[300100],vis[300100],now[300100];
    vector<int>v[300100];
    priority_queue<pair<int,int> >ql,qr;
    inline void dfs(int x){
        if(now[x]){
          puts("-1");
          exit(0);
        }else if(vis[x])return;
        now[x]=1;
        for(int i=0;i<v[x].size();i++){
          dfs(v[x][i]);
          ri[x]=min(ri[x],ri[v[x][i]]-1);
        }
        vis[x]=1;
        now[x]=0;
    }
    int main(){
        int i,j,k;
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)scanf("%d%d",&le[i],&ri[i]);
        for(i=1;i<=m;i++){
          int x,y;
          scanf("%d%d",&x,&y);
          v[x].pb(y);
          d[y]++;
          ri[x]=min(ri[x],ri[y]);
        }
        for(i=1;i<=n;i++)
          if(!d[i]&&!vis[i])dfs(i);
        for(i=1;i<=n;i++)
          if(!d[i])ql.push(mp(-le[i],i));
        T=1;
        while(!ql.empty()&&-ql.top().fi<=T)
            qr.push(mp(-ri[ql.top().se],ql.top().se)),ql.pop();
        while(!qr.empty()){
          int x=qr.top().se;qr.pop();
          if(ri[x]<T){
              puts("-1");
              return 0;
          }
          id[T]=x;T++;
          for(i=0;i<v[x].size();i++)
            if(d[v[x][i]]){
              d[v[x][i]]--;
              if(!d[v[x][i]])ql.push(mp(-le[v[x][i]],v[x][i]));
            }
          while(!ql.empty()&&-ql.top().fi<=T)
              qr.push(mp(-ri[ql.top().se],ql.top().se)),ql.pop();
        }
        for(i=1;i<=n;i++)if(!id[i]){puts("-1");return 0;}
        for(i=1;i<=n;i++)printf("%d
    ",id[i]);
        return 0;
    }
  • 相关阅读:
    关于进程exit后,内存释放释放的实践
    《C语言基础日常笔记》
    阿里巴巴重磅推出,让你的电脑变成云服务器,只要 5 分钟! 5 分钟! 5 分钟!
    vs2010下使用绘图控件MsChart的方法
    归纳整理Linux下C语言常用的库函数----文件操作
    归纳整理Linux下C语言常用的库函数----字符串转换、字符测试、及内存控制
    参考 generate-parentheses
    初步整理数仓知识 2017
    论文学习 数码相机系统
    论文学习:数码相机处理器的结构设计
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9887165.html
Copyright © 2011-2022 走看看