独立集

2 篇文章 0 订阅

题目描述
有一天,一个名叫顺旺基的程序员从石头里诞生了。又有一天,他学会了冒泡排序和独立集。在一个图里,独立集就是一个点集,满足任意两个点之间没有边。于是他就想把这两个东西结合在一起。众所周知,独立集是需要一个图的。那么顺旺基同学创造了一个算法,从冒泡排序中产生一个无向图。
这个算法不标准的伪代码如下:
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的一个全排列。

输出
两行。第一行输出最大独立集的大小,第二行从小到大输出一定在最大独立集的点的编号(输入时的序号)。
样例输入
3
3 1 2
样例输出
2
2 3
提示
【数据范围】
30%的数据满足 N<=16
60%的数据满足 N<=1,000
100%的数据满足 N<=100,000

多列几个数据,就可以发现最大独立集大小,就是最长不下降子序列大小。难点就是求一定在最长不下降子序列的元素。我们从1到n求一遍最长不下降子序列,从n到1做一遍最长不下降子序列。每次记录位置,如果两次位置相加为答案且这一位置只有这一个数,那么它就是。

var
n,i,l,r,mid,len,m,num,j,v,tot,ii,ans:longint;
a,d,b,dp,dp2,sum:array[0..200011] of longint;
function max(a,b:longint):longint;
begin
  if a>b then exit(a) else exit(b);
end;

begin
  readln(n);
  for i:=1 to n do
    read(a[i]);
  for i:=1 to n do
  begin
    l:=0;
    r:=len;
    while l<>r do
    begin
      mid:=(l+r+1) div 2;
      if d[mid]<a[i] then l:=mid
                     else r:=mid-1;
    end;
    l:=l+1;
    len:=max(len,l);
    d[l]:=a[i];
    dp[i]:=l;
  end;
  writeln(len);
  ans:=len;
  d[0]:=maxlongint;
  len:=0;
  for i:=n downto 1 do
  begin
    l:=0;
    r:=len;
    while l<>r do
    begin
      mid:=(l+r+1) div 2;
      if d[mid]>a[i] then l:=mid
                     else r:=mid-1;
    end;
    l:=l+1;
    len:=max(len,l);
    d[l]:=a[i];
    dp2[i]:=dp[i]+l-1;
    if dp2[i]=ans then sum[dp[i]]:=sum[dp[i]]+1;
  end;
  for i:=1 to n do
  begin
    if (dp2[i]=ans)and(sum[dp[i]]=1) then
    begin
      m:=m+1;
      b[m]:=i;
    end;
  end;
  for i:=1 to m do
    if i<>m then write(b[i],' ') else write(b[i]);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值