Quantifier Question

有长度为 \(n\) 的序列 \(x\{n\}\),有 \(m\) 个条件 \((j_i,k_i)\)。有 \(n\) 个待定的条件符 \(Q_i\in\{\forall,\exists\}\),使

\[Q_1x_1,Q_2x_2,...,Q_nx_n,(x_{j_1}<x_{k_1})∧(x_{j_2}<x_{k_2})∧\cdots∧(x_{j_m}<x_{k_m})
\]

求 \(\forall\) 最多的方案。如果没有满足方案,输出 \(-1\)。否则输出 \(\forall\) 的数量及整个条件符串。

数据范围:\(2\le n\le 2\cdot 10^5\),\(1\le m\le 2\cdot 10^5\),\(1\le j_i,k_i\le n,j_i\not=k_i\)。


一句话题解:拓扑排序,有环输出 \(-1\),否则将每个不被前后节点影响的节点置为 \(\forall\)。


首先理解一下,不同序号的 \(Q_i\) 是有顺序的,不是平等的。如 \(x_1<x_2\),\(x_1<x_3\),令 \(Q_1=\exists,Q_2=\forall,Q_3=\forall\) 是不可以的(如选定 \(x_1\) 后取 \(x_2=x_1-1\) 就爆了);但是如果 \(x_3<x_1,x_3<x_2\),令 \(Q_1=\exists,Q_2=\forall,Q_3=\forall\) 是可以的

先用差分约束的思想,把条件转化为边,即连 \(j_i\to k_i\)。然后拓扑排序。如果拓扑排序序列长度 \(<n\),说明有环,无解,输出 \(-1\)。否则存下这个拓扑序列。

设 \(u<v\),因为先发挥 \(u\) 的条件符再发挥 \(v\) 的条件符。所以如果 \(u\) 可以走到 \(v\) 或者 \(v\) 可以走到 \(u\),那么 \(v\) 点就不能选 \(\forall\) 了;反之,如果对于 \(v\),不存在 \(u<v\) 可以走到它或被它走到,这样的节点条件符选 \(\forall\) 是最优且没有后效性的。

然后用类似 \(\texttt{dp}\) 的方法,求出每个节点的最小前驱(可以走到它)和最小后继(它可以走到),然后如果最小前驱和最小后继都不小于该节点编号,那么该节点的条件符选 \(\forall\)。


时间复杂度 \(\Theta(n+m)\)。


代码:

#include <bits/stdc++.h>
using namespace std; //Start
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair(a,b)
#define x(a) a.first
#define y(a) a.second
#define b(a) a.begin()
#define e(a) a.end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f; //Data
const int N=2e5;
int n,m,d[N+7],f[N+7],b[N+7],sm,ans[N+7];
vector<int> e[N+7],g[N+7]; //Bfs
int Bfs(vector<int>&q){ //就是拓扑排序
//将图的拓扑序存入q,如果形成了环就返回0。
q.clear();
for(int i=1;i<=n;i++)if(!d[i]) q.pb(i);
for(int i=0;i<sz(q);i++)
for(int to:e[q[i]])if(!--d[to]) q.pb(to);
return sz(q)==n;
} //Main
int main(){
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;i++) scanf("%d%d",&u,&v),e[u].pb(v),g[v].pb(u);
for(int i=1;i<=n;i++) d[i]=sz(g[i]); //d为入度
vector<int> tp;
if(!Bfs(tp)) return puts("-1"),0;
iota(f+1,f+n+1,1),iota(b+1,b+n+1,1); //将fi:=i,bi:=i。
for(int i=0;i<=sz(tp)-1;i++)
for(int to:g[tp[i]]) f[tp[i]]=min(f[tp[i]],f[to]); //最小前驱
for(int i=sz(tp)-1;i>=0;i--)
for(int to:e[tp[i]]) b[tp[i]]=min(b[tp[i]],b[to]); //最小后继
for(int i=1;i<=n;i++)if(min(f[i],b[i])==i) sm++,ans[i]=1; //讲解中说了
printf("%d\n",sm);
for(int i=1;i<=n;i++) putchar("EA"[ans[i]]);puts("");
return 0;
}

祝大家学习愉快!

题解-Quantifier Question的更多相关文章

  1. CF R639 div 2 E Quantifier Question 数学 dfs 图论

    LINK:Quantifier Question 题面过长 引起不适 读题花了好长时间 对于 和 存在符合不是很熟练 导致很懵逼的做完了. 好在还算很好想.不过wa到了一个坑点上面 自闭一大晌 还以为 ...

  2. HDU 5793 A Boring Question (逆元+快速幂+费马小定理) ---2016杭电多校联合第六场

    A Boring Question Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  3. noip2007提高组题解

    题外话:这一年的noip应该是最受大众关心的,以至于在百度上输入noip第三个关键字就是noip2007.主要是由于这篇文章:http://www.zhihu.com/question/2110727 ...

  4. 多校6 1001 HDU5793 A Boring Question (推公式 等比数列求和)

    题解:http://bestcoder.hdu.edu.cn/blog/ 多校6 HDU5793 A Boring Question // #pragma comment(linker, " ...

  5. 2016多校第六场题解(hdu5793&hdu5794&hdu5795&hdu5800&hdu5802)

    这场就做出一道题,怎么会有窝这么辣鸡的人呢? 1001 A Boring Question(hdu 5793) 很复杂的公式,打表找的规律,最后是m^0+m^1+...+m^n,题解直接是(m^(n+ ...

  6. hdu_5793_A Boring Question(打表找规律)

    题目链接:hdu_5793_A Boring Question 题意: 自己看吧,说不清楚了. 题解: 打表找规律 #include<cstdio> typedef long long l ...

  7. LeetCode题解33.Search in Rotated Sorted Array

    33. Search in Rotated Sorted Array Suppose an array sorted in ascending order is rotated at some piv ...

  8. leetcode & lintcode 题解

    刷题备忘录,for bug-free 招行面试题--求无序数组最长连续序列的长度,这里连续指的是值连续--间隔为1,并不是数值的位置连续 问题: 给出一个未排序的整数数组,找出最长的连续元素序列的长度 ...

  9. HDU 5793 A Boring Question (找规律 : 快速幂+乘法逆元)

    A Boring Question Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

随机推荐

  1. JAVA 去除字符串前后的指定字符

    为了显示效果更好,我们可以将多余的字符去掉,代码如下: /** *去掉字符串前后的指定字符 */ public static String trimBothChars(String str, Stri ...

  2. android开发导包升级到androidx踩坑记录【转载】

    最近一直在做安卓开发,奈何手中的资料比较老,资料上的一些Import经常没有,十分让人头疼. 感谢简书上的[张晴天天天天天]做的整理. 在这里也记录一下备用. 升级Android Studio后,在 ...

  3. unity 顶点弹性网格效果

    1.球衰减 首先,我们将处理球衰减,鼠标或手指点中网格的点是碰撞点,越往外它所受的影响越小.我们需要从CPU中获取"_ImpactPos"这个碰撞点,获取摄像机和碰撞点的矢量,我们 ...

  4. powershell过杀软工具-xencrypt

           在红队攻击中,绕杀软是一个比较常见的技术.对于绕过杀软的方法,有基于黑白名单的,有基于shellloader的,也有基于加密与混淆的.最近在发现了这样一款过杀软的工具,推荐给有缘人,嘻嘻 ...

  5. scala中的val,var和lazy

    转自:https://yerias.github.io/2020/03/19/scala/3/#3%EF%BC%9Alazy%E4%BF%AE%E9%A5%B0%E7%AC%A6%E5%8F%AF%E ...

  6. MindManager 2021 版新增了哪些功能

    MindManager Windows 21是一款强大的可视化工具和思维导图软件,在工作应用中有出色的表现.今天就带大家来看下这个新版本增加了哪些功能? 1.新增现代主题信息样式MindManager ...

  7. 如何改变CorelDRAW的外观主题皮肤?

    CorelDRAW,我们通常也简称为CDR,是一款专业而且使用广泛的矢量图形绘制软件,也常用于绘制图形以及平面设计中.今天我们以CorelDRAW 2020来为大家演示一下,如何改变CorelDRAW ...

  8. FL studio系列教程(九):FL Studio中如何排列编曲

    在FL Studio水果音乐制作软件播放列表中可以对制作的样本进行编排,除此之外,播放列表中排列的对象被叫做剪辑.在其中可以排列以下剪辑. 1.样本剪辑:样本剪辑包含了编排好的插件乐器音符数据. 2. ...

  9. yum安装软件时报错libmysqlclient.so.18()(64bit)

    错误信息 yum -y install sysbench 安装sysbench提示缺少依赖包如下图: 主要原因 缺少Percona-XtraDB-Cluster-shared-55-5.5.37-25 ...

  10. Java集合【6.1】-- Collection接口源码详解

    目录 一.Collection接口简介 二.Collection源码分析 三.Collection的子类以及子类的实现 3.1 List extend Collection 3.2 Set exten ...