C. Quantifier Question

目录

1.Problem

2.Input

3.Output

4.Examples

4.1input

4.2output

5.Code

6.Conclusion


1.Problem

Logical quantifiers are very useful tools for expressing claims about a set. For this problem, let's focus on the set of real numbers specifically. The set of real numbers includes zero and negatives. There are two kinds of quantifiers: universal (∀∀) and existential (∃∃). You can read more about them here.

The universal quantifier is used to make a claim that a statement holds for all real numbers. For example:

  • ∀x,x<100∀x,x<100 is read as: for all real numbers xx, xx is less than 100100. This statement is false.
  • ∀x,x>x−1∀x,x>x−1 is read as: for all real numbers xx, xx is greater than x−1x−1. This statement is true.

The existential quantifier is used to make a claim that there exists some real number for which the statement holds. For example:

  • ∃x,x<100∃x,x<100 is read as: there exists a real number xx such that xx is less than 100100. This statement is true.
  • ∃x,x>x−1∃x,x>x−1 is read as: there exists a real number xx such that xx is greater than x−1x−1. This statement is true.

Moreover, these quantifiers can be nested. For example:

  • ∀x,∃y,x<y∀x,∃y,x<y is read as: for all real numbers xx, there exists a real number yy such that xx is less than yy. This statement is true since for every xx, there exists y=x+1y=x+1.
  • ∃y,∀x,x<y∃y,∀x,x<y is read as: there exists a real number yy such that for all real numbers xx, xx is less than yy. This statement is false because it claims that there is a maximum real number: a number yy larger than every xx.

Note that the order of variables and quantifiers is important for the meaning and veracity of a statement.

There are nn variables x1,x2,…,xnx1,x2,…,xn, and you are given some formula of the form

f(x1,…,xn):=(xj1<xk1)∧(xj2<xk2)∧⋯∧(xjm<xkm),f(x1,…,xn):=(xj1<xk1)∧(xj2<xk2)∧⋯∧(xjm<xkm),

where ∧∧ denotes logical AND. That is, f(x1,…,xn)f(x1,…,xn) is true if every inequality xji<xkixji<xki holds. Otherwise, if at least one inequality does not hold, then f(x1,…,xn)f(x1,…,xn) is false.

Your task is to assign quantifiers Q1,…,QnQ1,…,Qn to either universal (∀∀) or existential (∃∃) so that the statement

Q1x1,Q2x2,…,Qnxn,f(x1,…,xn)Q1x1,Q2x2,…,Qnxn,f(x1,…,xn)

is true, and the number of universal quantifiers is maximized, or determine that the statement is false for every possible assignment of quantifiers.

Note that the order the variables appear in the statement is fixed. For example, if f(x1,x2):=(x1<x2)f(x1,x2):=(x1<x2) then you are not allowed to make x2x2 appear first and use the statement ∀x2,∃x1,x1<x2∀x2,∃x1,x1<x2. If you assign Q1=∃Q1=∃ and Q2=∀Q2=∀, it will only be interpreted as ∃x1,∀x2,x1<x2∃x1,∀x2,x1<x2.

2.Input

The first line contains two integers nn and mm (2≤n≤2⋅1052≤n≤2⋅105; 1≤m≤2⋅1051≤m≤2⋅105) — the number of variables and the number of inequalities in the formula, respectively.

The next mm lines describe the formula. The ii-th of these lines contains two integers jiji,kiki (1≤ji,ki≤n1≤ji,ki≤n, ji≠kiji≠ki).

3.Output

If there is no assignment of quantifiers for which the statement is true, output a single integer −1−1.

Otherwise, on the first line output an integer, the maximum possible number of universal quantifiers.

On the next line, output a string of length nn, where the ii-th character is "A" if QiQi should be a universal quantifier (∀∀), or "E" if QiQi should be an existential quantifier (∃∃). All letters should be upper-case. If there are multiple solutions where the number of universal quantifiers is maximum, print any.

4.Examples

4.1input

2 1
1 2

4.2output

1
AE

5.Code

#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

template <typename T>
bool chkmax(T &x, T y) {
    return x < y ? x = y, true : false;
}

template <typename T>
bool chkmin(T &x, T y) {
    return x > y ? x = y, true : false;
}

int readint() {
    int x = 0, f = 1;
    char ch = getchar();
    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;
}

int main() {
    int n, m;
    n = readint();
    m = readint();
    
    vector<int> du(n + 1, 0);
    vector<int> q(n);
    vector<int> min1(n + 1, INT_MAX);
    vector<int> min2(n + 1, INT_MAX);
    vector<char> ans(n + 1, 'E');
    vector<bool> vis(n + 1, false);
    vector<vector<int>> adj(n + 1);

    for (int i = 1; i <= m; i++) {
        int x, y;
        x = readint();
        y = readint();
        adj[x].push_back(y);
        du[y]++;
    }

    int front = 0, rear = 0;
    for (int i = 1; i <= n; i++)
        if (!du[i])
            q[rear++] = i;

    while (front < rear) {
        int t = q[front++];
        for (auto v : adj[t])
            if (!(--du[v]))
                q[rear++] = v;
    }

    if (rear < n)
        return printf("-1\n"), 0;

    for (int i = 0; i <= n - 1; i++)
        for (auto v : adj[q[i]])
            chkmin(min1[v], min(min1[q[i]], q[i]));

    for (int i = n - 1; i >= 0; i--)
        for (auto v : adj[q[i]])
            chkmin(min2[q[i]], min(min2[v], v));

    int cnt = 0;
    for (int i = 1; i <= n; i++)
        if (min1[i] > i && min2[i] > i)
            ans[i] = 'A', cnt++;

    printf("%d\n", cnt);
    puts(ans.data() + 1);

    return 0;
}

6.Conclusion

这段C++代码实现了一个图论算法,用于解决一种拓扑排序相关的问题。以下是主要功能和流程的简要介绍:

  1. 输入:

    • 通过readint函数读取两个整数 n 和 m,分别表示图中的节点数和边数。
    • 通过循环读取 m 条边,其中每条边连接两个节点。
  2. 数据结构定义:

    • 使用向量 du 记录每个节点的入度。
    • 使用向量 q 作为队列,用于拓扑排序。
    • 使用向量 min1 和 min2 记录每个节点的前两小的值。
    • 使用字符向量 ans 记录每个节点的状态。
  3. 图的建立和拓扑排序:

    • 构建邻接表 adj 表示图的连接关系,并计算每个节点的入度。
    • 将入度为0的节点加入队列 q,然后进行拓扑排序。
  4. 拓扑排序过程:

    • 使用队列 q 进行广度优先搜索,将每个出队的节点标记为已访问。
    • 对于每个出队的节点,更新其邻接节点的入度,若入度为0,则将其加入队列。
  5. 寻找前两小的值:

    • 根据拓扑排序的结果,计算每个节点的前两小的值,并保存在 min1 和 min2 中。
  6. 确定节点状态:

    • 根据计算得到的前两小的值,确定每个节点的状态,存储在字符向量 ans 中。
  7. 输出结果:

    • 输出满足条件的节点数和每个节点的状态。

总体而言,这段代码通过拓扑排序找到图中满足特定条件的节点,并输出相应的结果。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向阳而生__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值