[Gym 100228] Graph of Inversions

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Gym 100228] Graph of Inversions相关的知识,希望对你有一定的参考价值。

题意

  给定长度为 $n$ 的序列 $A = \left\{ a_1, a_2, ..., a_n \right\}$ .

  我们定义其逆序图 $G$ : 对于 $i < j$ , $i, j$ 之间存在连边 $\Leftrightarrow a_i > a_j$ .

  给定一个序列的逆序图, 求有多少个点集 $S$ , 满足 $S$ 既是独立集, 又是覆盖集.

  $n \le 1000$ .

 

分析

  我们考虑探究逆序图与原序列的关系.

  点集 $S$ 在逆序图中是独立集, 当且仅当在原序列中单调不降.

  点集 $S$ 在逆序图中是覆盖集, 当且仅当对于任意相邻的 $i, j$ , $i < j$ , 满足 $\forall k \in (i, j), a_i > a_k 或 a_k > a_j$ .

 

  我们考虑进行DP.

  可以利用单调性优化到 $O(n ^ 2)$ , 判定 $j$ 是否合法的时间复杂度为 $O(1)$ .

 

实现

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cctype>
 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
 6 #define P(i, a, b) for (register int i = (a); i >= (b); i--)
 7 #define LL long long
 8 inline int rd(void) {
 9     int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == -) f = -1;
10     int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-0; return x*f;
11 }
12 
13 const int N = 1005;
14 
15 int n, m;
16 bool g[N][N];
17 
18 LL f[N];
19 LL res;
20 
21 int main(void) {
22     #ifndef ONLINE_JUDGE
23         freopen("100228.in", "r", stdin);
24     #endif
25     
26     n = rd(), m = rd();
27     F(i, 1, m) {
28         int x = rd()+1, y = rd()+1;
29         g[x][y] = g[y][x] = true;
30     }
31     F(i, 0, n+1) g[i][n+1] = g[n+1][i] = true;
32     
33     f[0] = 1;
34     F(i, 1, n) {
35         int w = n+1;
36         P(j, i-1, 0)
37             if (!g[j][i] && g[j][w])
38                 f[i] += f[j], w = j;
39     }
40     int w = n+1;
41     for (int j = n; j >= 1; j--)
42         if (g[j][w])
43             res += f[j], w = j;
44     printf("%lld\n", res);
45     
46     return 0;
47 }

 

以上是关于[Gym 100228] Graph of Inversions的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces Gym 100228 Graph of Inversions

Gym 100801G Graph 拓扑排序

GYM - 100814 C.Connecting Graph

[CF1499G]Graph Coloring

Gym 101666K King of the Waves(dfs)

Gym - 101611D Decoding of Varints(边界值处理)