1. 程式人生 > >SSl 2756_獨立集_最長不下降子序列

SSl 2756_獨立集_最長不下降子序列

pri == clas stdio.h 我們 心情 [] 題目 can

題目描述

有一天,一個名叫順旺基的程序員從石頭裏誕生了。又有一天,他學會了冒泡排序和獨立集。在一個圖裏,獨立集就是一個點集,滿足任意兩個點之間沒有邊。於是他就想把這兩個東西結合在一起。眾所周知,獨立集是需要一個圖的。那麽順旺基同學創造了一個算法,從冒泡排序中產生一個無向圖。

這個算法不標準的偽代碼如下:
procedure bubblesortgraph(n, a[]) :
/*輸入:點數n,1到n的全排列a。
輸出:一個點數為n的無向圖G。*/
創建一個有n個點,0條邊的無向圖G。
repeat
swapped = false
for i 從 1 到 n-1 :
if a[i] > a[i + 1] :
在G中連接點a[i]和點a[i + 1]
交換a[i]和a[i + 1]
swapped = true
until not swapped
輸出圖G。
//結束。


那麽我們要算出這個無向圖G最大獨立集的大小。但是事情不止於此。順旺基同學有時候心情會不爽,這個時候他就會要求你再回答多一個問題:最大獨立集可能不是唯一的,但有些點是一定要選的,問哪些點一定會在最大獨立集裏。今天恰好他不爽,被他問到的同學就求助於你了。


思路

因為題目中是將i > j 的邊連起來,所以只用將數據跑一遍最長上升子序列就可以了

然後第二問就可以倒著跑一邊最長下降子序列,如果f[i] + fl[i] = max + 1 那麽就肯定是一個唯一的,也就是一個答案

還有如果f中有多個相同的話那這個肯定不會是一個答案


#include <stdio.h>
#include 
<algorithm> using namespace std; #define maxn 100001 #define INF 0x7f7f7f7f int a[maxn], f[maxn], fl[maxn], d[maxn], flaj[maxn]; int main() { int n; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); int last = 0; for (int i = 1; i <= n; i++) {
int t = lower_bound(d + 1, d + last + 1, a[i]) - d; if (last < t) last = t; f[i] = t; d[t] = a[i]; } printf("%d\n", last); last = 0; for (int i = n; i >= 1; i--) { int t = lower_bound(d + 1, d + last + 1, -a[i]) - d; if (last < t) last = t; fl[i] = t; d[t] = -a[i]; } for (int i = 1; i <= n; i++) if (f[i] + fl[i] == last + 1) flaj[f[i]]++; for (int i = 1; i <= n; i++) if (flaj[f[i]] == 1 && f[i] + fl[i] == last + 1) printf("%d ", i); }

SSl 2756_獨立集_最長不下降子序列