1. 程式人生 > 實用技巧 >獨立集(bubble) 題解

獨立集(bubble) 題解

問題描述

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

這個演算法不標準的虛擬碼如下:

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最大獨立集的大小。但是事情不止於此。順旺基同學有時候心情會不爽,這個時候他就會要求你再回答多一個問題:最大獨立集可能不是唯一的,但有些點是一定要選的,問哪些點一定會在最大獨立集裡。今天恰好他不爽,被他問到的同學就求助於你了。

輸入

兩行。第一行為N,第二行為1到N的一個全排列。

輸出

兩行。第一行輸出最大獨立集的大小,第二行從小到大輸出一定在最大獨立集的點的編號(輸入時的序號)。

輸入輸出樣例

bubble.in

3

3 1 2

bubble.out

2

2 3

30%的資料滿足 N<=16資料範圍

60%的資料滿足 N<=1,000

100%的資料滿足 N<=100,000

這道題的第一問其實就是最長上升子序列,第二問求必是最長上升子序列裡的元素有哪些,我們就只需要正著跑一遍再反著跑一遍就行了。

上程式碼

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int s=0,m=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')m=-1,ch=getchar();
    while(ch>='0'&&ch<='9')s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    return s*m;
}
int B[100005],sec;
int a[100005],b[100005];
int A[100005],fir;
int L[100005],R[100005];
int n;
map<pair<int, int>, int> Pair;
int main(){
    n=read();
    for(int i=1;i<=n;i++)
	{
       	a[i]=read();
        b[i]=-a[i];
    }
    for(int i=1;i<=n;i++)
	{
        int pos=lower_bound(A+1,A+1+fir,a[i])-A;
        L[i]=pos;
        fir+=int(A[pos]==0);
        A[pos]=a[i];
    }
    for(int i=1;i<=n;i++) B[i]=-1e9+7;
    for(int i=n;i>=1;i--)
	{
        int pos=lower_bound(B+1,B+1+sec,b[i])-B;
        R[i]=pos;
        sec+=int(B[pos]==-1e9+7);
        B[pos]=b[i];
    }
    cout<<fir<<endl;
    for(int i=1;i<=n;i++)
        if(L[i]+R[i]-1==fir)
            Pair[make_pair(L[i],R[i])]++;
    sec=0;
    for(int i=1;i<=n;i++)
        if(L[i]+R[i]-1==fir&&Pair[make_pair(L[i],R[i])]==1)
            B[++sec]=i;
    for(int i=1;i<=sec;i++)
        cout<<B[i]<<" ";
    return 0;
}