首页 > 其他分享 >[ABC304Ex] Constrained Topological Sort 题解

[ABC304Ex] Constrained Topological Sort 题解

时间:2023-12-11 12:33:18浏览次数:39  
标签:Sort head le 限制 ABC304Ex 题解 int MAXN define

题意

给定一张有向图 \(G\),有 \(n\) 个点和 \(m\) 条边,问是否存在一种拓扑序的排列 \(P\) 使得 \(l_{i} \le p_{i} \le r_{i}\)。

思路

首先对于一条边 \(u \to v\),如果限制满足 \(r_{v}\le r_{u}\) 或者 \(l_{v} \ge l_{u}\) 的话,那么这个限制其实是不完全正确的。因为最终的序列一定是一个拓扑序,所以一定有 \(p_{u} \le p_{v}\),而题目给定的限制是不一定满足这个条件的。所以应该将限制更改为:

\(l_{v}=\max(l_{v},l_{u} + 1),r_{u}=\min(l_{u},l_{v} + 1)\)。

对于 \(l\) 限制的更改应该在拓扑序上正序更改,而对于 \(r\) 的限制应该在拓扑序上倒序更改,因为前者是从 \(u\) 更新到 \(v\),而后者是从 \(v\) 更新到 \(u\)。

将限制修改后,考虑贪心。应该按照 \(r\) 从小到大的顺序来选择这些点,对于每一个点 \(u\),最终 \(u\) 点的位置应该满足 \(p_{u}\ge l_{u}\) 并且 \(p_{u}\) 应该尽量去接近 \(l_{u}\),因为这样选择位置后可以使后面 \(r\) 的值更大的点有更多的选择空间。这个操作可以用一个 \(set\) 来实现,每一次选择就相当于在 \(set\) 中间做一次二分查找第一个大于 \(l_{u}\) 的数,总时间复杂度 \(O(n \log n)\)。

注意还需要判断这个图是不是一个有向无环图,如果不是的话直接判断为不可能即可。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define inf 0x3f
#define inf_db 127
#define ls id << 1
#define rs id << 1 | 1
#define re register
#define endl '\n'
typedef pair <int,int> pii;
const int MAXN = 3e5 + 10;
int n,m,x,y,l[MAXN],r[MAXN],head[MAXN],cnt,din[MAXN],a[MAXN],tot,ans[MAXN];
struct Node{int u,v,nxt;}e[MAXN];
set <int> s;
vector <int> v[MAXN];
queue <int> q;
inline void Add(int u,int v){e[++cnt] = {u,v,head[u]};head[u] = cnt;}
signed main()
{
	memset(head,-1,sizeof head);
	cin >> n >> m;
	for(int i = 1;i <= m;i++) cin >> x >> y,Add(x,y),din[y]++;
	for(int i = 1;i <= n;i++) cin >> l[i] >> r[i];
	for(int i = 1;i <= n;i++) if(din[i] == 0) q.push(i);
	while(!q.empty())
	{
		int u = a[++tot] = q.front();q.pop();
		for(int i = head[u]; ~ i;i = e[i].nxt)
		{
			int now = e[i].v;
			l[now] = max(l[now],l[u] + 1);
			if(--din[now] == 0) q.push(now);
		}
	}
	if(tot < n){puts("No");return 0;}
	for(int i = tot;i >= 1;i--)
	{
		int u = a[i];
		for(int j = head[u]; ~ j;j = e[j].nxt)
		{
			int now = e[j].v;
			r[u] = min(r[u],r[now] - 1);
		}
		v[r[u]].emplace_back(u);
	}
	for(int i = 1;i <= n;i++)
	{
		s.insert(i);
		for(int j = 0;j < v[i].size();j++)
		{
			int u = v[i][j];
			auto k = s.lower_bound(l[u]);
			if(k == s.end()){puts("No");return 0;}
			ans[u] = *k,s.erase(k);
		}
	}
	puts("Yes");
	for(int i = 1;i <= n;i++) cout << ans[i] << " ";
	return 0; 
}

标签:Sort,head,le,限制,ABC304Ex,题解,int,MAXN,define
From: https://www.cnblogs.com/Creeperl/p/17894120.html

相关文章

  • 【题解】AtCoder abc322_f Random Update Query
    传送门:https://atcoder.jp/contests/abc332/tasks/abc332_f容易发现,对于一个位置$i$,$A_i$的最终值是由对$i$的最后一次赋值操作决定的;因此,将所有操作按时间顺序倒过来考虑,则由第$j$次操作决定$A_i$最终值的概率为"在第$(j+1)$~$m$次操作中没有修改过$i$的概率"与"第......
  • 【题解】AtCoder abc332_g Not Too Many Balls
    传送门:https://atcoder.jp/contests/abc332/tasks/abc332_g看完题,第一眼反应为最大流。建模方式为:以颜色为左部点,盒子为右部点,源点$S$向颜色$i$连一条容量为$A_i$的边,盒子$j$向汇点$T$连一条容量为$B_j$的边,颜色$i$向盒子$j$连一条容量为$ij$的边;在这张图......
  • AT_cf17_final_j Tree MST 题解
    题意:给定一颗\(n\)个点的树,点\(i\)有权值\(a_{i}\),边有边权。现在有另外一个完全图,两点之间的边权为树上两点之间的距离加上树上两点的点权,求这张完全图的最小生成树。首先有一个很显然的暴力,把完全图中每两点之间的边权算出来,然后跑一边最小生成树,时间复杂度\(O(n^{2}\lo......
  • P7735 [NOI2021] 轻重边 题解
    是一道树剖好题,之前听lsl讲过一点,于是很快就做出来了。题意:有一个\(n\)个节点的树,最开始的时候所有边都是轻边,维护两个操作:操作一:将\(u\)到\(v\)的路径中经过的所有点的邻边变为轻边,再将这条路径上的边变为重边。操作二:求出\(u\)到\(v\)这条路径上有多少条重边......
  • 小程序建立用户与数据的联系问题解决方案
    在小程序中建立用户与数据的联系是一个常见的问题,在本文中提供了一个解决方案。这个解决方案包括几个关键步骤。首先,需要通过用户登录功能实现用户的身份识别,并获取到用户的唯一标识符。接着,需要在后台数据库中创建一个用户表,用于存储用户的基本信息和与之相关联的数据。在这个表中......
  • ARC169 B Subsegments with Small Sums 题解
    LinkARC169BSubsegmentswithSmallSumsQuestion\(x\)是一个序列,定义\(f(x)\)为把序列\(x\)切成几段,每段的和不能超过\(S\)的最小段数给出序列\(A=(A_1,A_2,\cdots,A_N)\)求:\[\sum_{1\lel\leN}f((A_l,A_{l+1},\cdots,A_r))\]Question先考虑一个结论,\(x\)为......
  • P9915 「RiOI-03」3-2 题解
    更好的阅读这是一道找规律的题目。因为我个人习惯,以下部分使用从\(1\)开始的下标讲述。首先我们以\(1\)来说:发现在第\(x\)行\(y\)列的连通块是可以直接连到第\(1\)列的,所以很容易可以得出\(1\)到\(y\)列的连通块数量是\(2^y-1\)。接着,我们考虑再后面的情况:......
  • 【Cpp 基础】泛型算法 stable_sort() 的应用
    最近在刷牛客的题。经常遇到排序问题,经常有一个附加的规则:相同的数值的,按照录入的顺序排序。可是C++的sort()的底层是快速排序,并不能保证相同数值的顺序不改变。所以最后我不得不自己写冒泡排序。(冒泡排序不改变相同数值的录入顺序)写了那么多的排序,但是其实C++里封装有排序函数......
  • 常见问题解决 --- pip SSLEOFError
    问题C:\Users\Administrator\Desktop>pipinstallscapy-ihttp://pypi.douban.com/simple--trusted-hostpypi.douban.comLookinginindexes:http://pypi.douban.com/simpleWARNING:Retrying(Retry(total=4,connect=None,read=None,redirect=None,status=None......
  • 【题解】CQOI2017 - 小 Q 的表格
    【题解】CQOI2017-小Q的表格https://www.luogu.com.cn/problem/P3700首先考虑题面给的两个式子。由式二可以得到:\[\dfrac{f(a,a+b)}{a(a+b)}=\dfrac{f(a,b)}{ab}\]发现这个很像辗转相除,可得\[\dfrac{f(a,b)}{ab}=\dfrac{f(a,a\bmodb)}{a(a\bmodb)}\]然后由式一转换,最......