题解P5875 [IOI2014]friend 朋友

· · 题解

讲一个其他题解都没有的做法,甚至不需要开空间。

我真没用空间啊,是交互库开的关我啥事啊

题意简述

给定一张无向图,让你求最大权独立集。

但是最大权独立集是 NPC 问题,所以这个图有特殊的构造方式:

初始只有一个点 0,从 1n-1 依次加入点,每次加入点 i 时有三种选择:

  1. 给定 j,将 ij 连边;
  2. 给定 j,将 ij 的所有邻居连边;
  3. 给定 j,将 ijj 的所有邻居连边。

思路分析

我们考虑倒过来做,从大到小依次删掉点 i

分类讨论:

然后就过了,时间复杂度 O(n)

代码展示

```cpp #include<bits/stdc++.h> using namespace std; int findSample(int n,int* a,int* b,int* opt){ b[0]=0; while(--n) if(!opt[n])b[0]+=a[n],a[b[n]]=max(0,a[b[n]]-a[n]); else if(opt[n]==1)a[b[n]]+=a[n]; else a[b[n]]=max(a[b[n]],a[n]); return b[0]+a[0]; } ``` Update:有同学发现上面的代码会用到编译器的临时空间,写了个疑似不需要辅助空间的代码: ```cpp int findSample(int n, int a[], int b[], int opt[]) { *b = 0; while (--n) { opt += n; if (*opt) { if (*opt &= 1) { a += n, *opt = *a, a -= n; b += n, a += *b; *a += *opt; a -= *b, b -= n; } else { a += n, *opt = *a, a -= n; b += n; a += *b, *opt -= *a, a -= *b; *opt *= -1; *opt >>= 31; if (*opt) { a += n, *opt = *a, a -= n; a += *b, *a = *opt, a -= *b; } b -= n; } } else { a += n, *b += *a, a -= n; b += n; a += n, *opt = *a, a -= n; a += *b; *a -= *opt; *opt = *a, *opt >>= 31; if (*opt) *a = 0; a -= *b; b -= n; } opt -= n; } return *b += *a; } ```