原题地址:https://codeforces.com/gym/102059/problem/D
题意: n n n 个人要排成一排,每个人想要站的位置都是一个区间,同时还有一些形如“ x x x必须站在 y y y左边”的限制,构造一组方案。
思路:如果只有后面的
x
x
x在
y
y
y的前面的限制,那么这就是一个简单的拓扑排序。但是这里还有区间的限制。
考入如果有
x
x
x点的范围是
[
l
1
,
r
1
]
[l_1,r_1]
[l1,r1],
y
y
y点的范围是
[
l
2
,
r
2
]
[l_2,r_2]
[l2,r2],并且
x
x
x点在
y
y
y点的前面。
那么显然,x点的范围一定是
[
l
1
,
m
i
n
(
r
1
,
r
2
−
1
)
]
[l_1,min(r_1,r_2-1)]
[l1,min(r1,r2−1)],经过这种处理之后,所有点的所在范围都是在一个区间内且一条链上的都是不相交的。
所以我们拓扑排序构造,把所有入度为
0
0
0的点都加入到一个优先队列中,注意是个最小堆。
然后我们把所有起点小于当前要处理的位置
p
o
s
pos
pos的点都加入到另外一个优先队列中,这是个最小堆。表示把所有符合条件的让区间的右端点
r
r
r小的先填入。
就这样子贪心的构造。
#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x, y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 3e5 + 5;
const int mod = 1e9 + 7;
int n, m;
int l[maxn], r[maxn];
vector<int> G[maxn];
int into[maxn];
int vis[maxn];
int find(int u) {
if (vis[u]) return r[u];
vis[u] = 1;
for (int i = 0; i < (int) G[u].size(); i++) {
int v = G[u][i];
r[u] = min(r[u], find(v) - 1);
}
return r[u];
}
//存放拓扑中的点,入度为0
struct node {
int l, r, id;
//l小的在前面
friend bool operator<(node a, node b) {
return a.l > b.l;
}
};
typedef pair<int, int> pii;
int ans[maxn];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &l[i], &r[i]);
}
for (int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
into[v]++;
}
priority_queue<node> q;
priority_queue<pii> pq;
for (int i = 1; i <= n; i++) {
r[i] = find(i);
if (into[i] == 0) {
q.push(node{l[i], r[i], i});
}
}
int now = 1;
while (1) {
while (!q.empty() && q.top().l <= now) {
node tmp = q.top();
q.pop();
pq.push(make_pair(-tmp.r, tmp.id));
}
if (pq.empty()) break;
pii tmp = pq.top();
pq.pop();
int u = tmp.second;
if (r[u] < now) {
printf("-1\n");
return 0;
}
ans[now++] = u;
for (int i = 0; i < (int) G[u].size(); i++) {
int v = G[u][i];
into[v]--;
if (into[v] == 0) q.push(node{l[v], r[v], v});
}
}
if (now <= n) printf("-1\n");
else {
for (int i = 1; i <= n; i++) {
printf("%d\n", ans[i]);
}
}
return 0;
}