[SDOI2019] 热闹的聚会与尴尬的聚会
作者:互联网
前言
在洛谷题解逛了一圈,不是随机化乱搞就是带log的做法,这里来一个线性且正确性有保证的做法。
人傻常数大,打不过随机化/kk
题目
讲解
做法是每次删除度最小的点,贪心加入独立集。因为很多题解都证过了,这里就不证正确性了。
讲一下实现。
我们对每个点按度数桶排,然后可以从小到大枚举 \(p\),每次删除度数不超过 \(p\) 的点并且动态更新度数,度数如果减小到删除条件就直接删掉,可以递归实现。
在删除过程中同样可以维护独立集,值得注意的是打独立集的 tag 的时候要先打再递归去删数,不然会出问题。
卡常技巧是不用 vector
而是用链表。
具体实现可以看代码。
代码
//12252024832524
#include <bits/stdc++.h>
#define TT template<typename T>
using namespace std;
typedef long long LL;
const int MAXN = 10005;
int n,m;
char buf[1<<21],*p1=buf,*p2=buf;
#define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
LL Read()
{
LL x = 0,f = 1;char c = getchar();
while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
return x * f;
}
TT void Put1(T x)
{
if(x > 9) Put1(x/10);
putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
if(x < 0) putchar('-'),x = -x;
Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}
int head[MAXN],tot,deg[MAXN],hd[MAXN];
struct edge{
int v,nxt;
}e[MAXN*45];
void Add_Edge(int u,int v){
e[++tot] = edge{v,head[u]};
head[u] = tot;
}
void Add_Double_Edge(int u,int v){
Add_Edge(u,v);
Add_Edge(v,u);
++deg[u]; ++deg[v];
}
bool used[MAXN],del[MAXN];
int ans1[MAXN],ans2[MAXN],t1,t2,MAX;
void clr(int x,int p){
del[x] = 1; ans1[++t1] = x;
bool sg = 0;
if(!used[x]) ans2[++t2] = x,used[x] = sg = 1;
if(sg) for(int i = head[x]; i ;i = e[i].nxt) used[e[i].v] = 1;//先打tag
for(int i = head[x],v; i ;i = e[i].nxt) {//后删数字
if(del[v = e[i].v]) continue;
--deg[v];
if(deg[v] <= p) clr(v,p);
else e[++tot] = edge{v,hd[deg[v]]},hd[deg[v]] = tot;
}
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
for(int T = Read(); T ;-- T){
n = Read(); m = Read(); t1 = t2 = tot = MAX = 0;
for(int i = 0;i <= n;++ i) head[i] = deg[i] = hd[i] = used[i] = del[i] = 0;
for(int i = 1;i <= m;++ i) Add_Double_Edge(Read(),Read());
for(int i = 1;i <= n;++ i) e[++tot] = edge{i,hd[deg[i]]},hd[deg[i]] = tot;
for(int p = 0;p < n;++ p){
for(int i = hd[p]; i ;i = e[i].nxt){
int x = e[i].v;
if(del[x]) continue;
if(p > MAX) MAX = p,t1 = 0; clr(x,p);
}
}
Put(t1,' ');
for(int i = 1;i <= t1;++ i) Put(ans1[i],' '); putchar('\n');
Put(t2,' ');
for(int i = 1;i <= t2;++ i) Put(ans2[i],' '); putchar('\n');
}
return 0;
}
标签:head,int,TT,++,尴尬,MAXN,聚会,SDOI2019,deg 来源: https://www.cnblogs.com/PPLPPL/p/16079059.html