生活随笔
收集整理的這篇文章主要介紹了
【动态规划】【图论】[NOIP模拟赛]独立集
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述:
有一天,一個名叫順旺基的程序員從石頭里誕生了。又有一天,他學會了冒泡排序和獨 立集。在一個圖里,獨立集就是一個點集,滿足任意兩個點之間沒有邊。于是他就想把這兩 個東西結合在一起。眾所周知,獨立集是需要一個圖的。那么順旺基同學創造了一個算法, 從冒泡排序中產生一個無向圖。
這個算法不標準的偽代碼如下:
void bubblesortgraph(n,a[])
//輸入:點數n,1到n的全排列a
//輸出:一個點數為n的無向圖G
{ 創建一個有n個點,0條邊的無向圖G。
do{ 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
}
}while(swapped);
輸出圖G。
}
//結束。
那么我們要算出這個無向圖G最大獨立集的大小。但是事情不止于此。順旺基同學有時 候心情會不爽,這個時候他就會要求你再回答多一個問題:最大獨立集可能不是唯一的,但 有些點是一定要選的,問哪些點一定會在最大獨立集里。今天恰好他不爽,被他問到的同學 就求助于你了。
首先可以發現一定是在當前序列中的最長上升子序列,但是怎么才能判斷當前數字一定在所有的最長上升子序列中呢?可以判斷(以當前為開始的向左邊的最長下降子序列,以當前為開始的向右的最長上升子序列)的二元組是唯一的否則一定有另一個可以替換,弄兩次最長上升子序列就行了,具體的優化方法自己百度吧
輸入
3
3 1 2
輸出
2
2 3
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
#include <cstring>
using namespace std;
const int MAXN =
100000;
const int INF =
1e9+
7;
int B[MAXN+
10], LenB;
int a[MAXN+
10], b[MAXN+
10];
int A[MAXN+
10], LenA;
int L[MAXN+
10], R[MAXN+
10];
map<pair<int, int>,
int> check;
void Clear(
int *s,
int v,
int n){
for(
int i=
0;i<=n;i++)B[i] = v;
}
int main(){
int n;
scanf(
"%d", &n);
for(
int i=
1;i<=n;i++){
scanf(
"%d", &a[i]);b[i] = -a[i];}
for(
int i=
1;i<=n;i++){
int pos = lower_bound(A+
1, A+
1+LenA, a[i]) - A;L[i] = pos;LenA +=
int(A[pos] ==
0);A[pos] = a[i];}
for(
int i=
1;i<=n;i++) B[i] = -INF;
for(
int i=n;i>=
1;i--){
int pos = lower_bound(B+
1, B+
1+LenB, b[i]) - B;R[i] = pos;LenB +=
int(B[pos] == -INF);B[pos] = b[i];}
printf(
"%d\n", LenA);
for(
int i=
1;i<=n;i++)
if(L[i] + R[i] -
1 == LenA)check[make_pair(L[i], R[i])]++;LenB=
0;
for(
int i=
1;i<=n;i++)
if(L[i] + R[i] -
1 == LenA && check[make_pair(L[i], R[i])] ==
1)B[++LenB] = i;
for(
int i=
1;i<=LenB;i++)
printf(
"%d ", B[i]);
return 0;
}
轉載于:https://www.cnblogs.com/JeremyGJY/p/5921659.html
總結
以上是生活随笔為你收集整理的【动态规划】【图论】[NOIP模拟赛]独立集的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。