10.31 zroj 数分考试

题意

上了大学后,小S迎来了自己的第一次数分考试。一共有nn个人参加了考试。

无聊的助教决定不告诉大家每个人的名次,而是让大家自己猜。

首先,大家知道了第ii个人的名次区间是[Li,Ri][Li,Ri]。

除此之外,又有mm条其他信息,形如ui,viui,vi,表示第uiui个人考的要比vivi好(即排名更低)。

现在,小S想要知道,是否有一个合法的排名,满足上述所有的要求。如果有,请输出任意一组解,否则输出"-1"(不含括号)。
输入格式

第一行两个整数 n,mn,m,表示人数和限制条数。

接下来nn行,每行两个正整数Li,RiLi,Ri。

接下来mm行,每行两个正整数ui,viui,vi。
输入格式

如果无解输出-1。

否则输出nn行,每行11个整数,其中第ii个表示第ii名的id。编号从1开始。
样例1
input

3 3
1 3
1 3
1 3
1 2
2 3
3 1

output

-1

样例2
input

3 3
1 3
1 3
1 3
1 2
2 3
1 3

output

1
2
3

限制与约定

对于 10%10% 的数据,满足 n,m≤10n,m≤10。

对于 30%30% 的数据,满足 n,m≤100n,m≤100。

对于 60%60% 的数据,满足 n≤105,m≤105n≤105,m≤105。

对于 100%100% 的数据,满足 n≤3×105,m≤106n≤3×105,m≤106。

时间限制:2 s

空间限制:512 MB
故事的后续

小S虽然考了97,但是他惊喜地发现全班的前25%25%是96分。

思路??

  1. 考虑topsort,但topsort每个位置必定不唯一,那么我们就把i的topsort尽量移动到给定的【li,ri】里。
  2. 假如我们的topsort已经考虑到第x位,那么任意li<x的i都可以成为本个位置的元素,我们优先把r小的放在此位置
  3. 用两个priority_queue维护一下

code ?? 10分

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstdlib>
#include<ctime>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
inline int read(){
	char ch=' ';int f=1;int x=0;
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
const int N=3e5+100;
const int M=1e6+100;
int l[N],r[N];
struct node
{
	int v,nxt;
	int w;
}edge[M];
int head[N],cnt;
void add(int u,int v)
{
	cnt++;
	edge[cnt].v=v;
	edge[cnt].nxt=head[u];
	head[u]=cnt;
}
int in[N];
int topsort[N];
priority_queue <pair<int,int> > q;
priority_queue <pair<int,int> > qr;
int main()
{
	int n,m;
	n=read();m=read();
	int i,j;
	for(i=1;i<=n;i++)
	{
		l[i]=read();
		r[i]=read();
	}
	for(i=1;i<=m;i++)
	{
		int u,v;
		u=read();v=read();
		add(u,v);
		in[v]++;
	}
	for(i=1;i<=n;i++)
	{
		if(in[i]==0)
		{
			q.push(make_pair(l[i],i));
		}
	}
	int cnt=1;
	int x;
	for(i=1;i<=n;i++)
	{
		if(!q.empty()) x=q.top().second;
		else
		{
			cout<<"-1"<<endl;
			return 0;
		}
		while(l[x]<=cnt)
		{
			q.pop();
			qr.push(make_pair(r[x],x));
			if(!q.empty())
			{
				x=q.top().second;
			}
			else
			{
				break;
			}
		}
		if(!qr.empty())
		{
			x=qr.top().second;
			qr.pop();
		}
		else
		{
			cout<<"-1"<<endl;
			return 0;
		}
		if(r[x]>=cnt)
		{
			topsort[cnt]=x;cnt++;
			for(j=head[x];j;j=edge[j].nxt)
			{
				int v=edge[j].v;
				in[v]--;
				if(in[v]==0)
				{
					q.push(make_pair(l[v],v));
				}
			}
		}
		else
		{
			cout<<"-1"<<endl;
			return 0;
		}
	}
	for(i=1;i<=n;i++)
	{
		cout<<topsort[i]<<endl;
	}
	return 0;
}


zj
https://www.cnblogs.com/yzxverygood/p/9887165.html

#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\n",id[i]);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值