[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 - 100814 C.Connecting Graph