数分考试

112 篇文章 0 订阅

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们就是要对⼀个DAG求⼀个拓扑序,使得第i个的顺序在(li,ri)中。
⾸先,我们先把这个ri的限制收紧,让它变成⼀个真的限制考虑我们平时求⼀个拓扑序都是⽤⼀个队列维护,我们现在为了满⾜ri的限制,我们⽤⼀个优先队列维护这个队列。
假设现在要求字典序的第r个东⻄,那么可以把所有已经被扩展过的且li=t的加⼊单调队列。
接着,从单调队列⾥选出ri最⼩的⼀个点来扩展,把它作为字典序的第t个。

#include<bits/stdc++.h>
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\n",id[i]);
 return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值