Luogu

LOJ

分析

题目中的条件相当于 $(p+1)(q+1)\geq n$。

第一问可以每次选一个度数最小的点删去,然后更新答案。用堆维护可以做到 $\mathcal{O}(n\log n)$。

第二问是求独立集,也可以每次选一个度数最小的点,然后把它和与它相连的点都删去。

可以证明这样子一定是满足条件的。设第 $i$ 次删掉的点的度数为 $d_i$,那么有 $\sum_{i=1}^q(d_i+1)\geq n$,而 $p=\max\{d_i\}$,故 $(p+1)(q+1)\geq n$ 必成立。

当然你也可以直接随机化来戏弄出题人

代码

// ====================================
//   author: M_sea
//   website: https://m-sea-blog.com/
// ====================================
#include <bits/stdc++.h>
#define file(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
#define debug(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;

int read() {
    int X=0,w=1; char c=getchar();
    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
    while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
    return X*w;
}

const int N=10000+10;

int n,m,deg[N],odeg[N],vis[N];
vector<int> E[N],vp,vq;
priority_queue<pii,vector<pii>,greater<pii>> Q;

int main() {
    int T=read();
    while (T--) {
        n=read(),m=read();
        for (int i=1;i<=m;++i) {
            int u=read(),v=read();
            E[u].emplace_back(v),++odeg[v];
            E[v].emplace_back(u),++odeg[u];
        }
        memset(vis,0,sizeof(vis)),memcpy(deg,odeg,sizeof(deg));
        int mxp=n,pos=0;
        for (int i=1;i<=n;++i) Q.emplace(deg[i],i),mxp=min(mxp,deg[i]);
        while (!Q.empty()) {
            int u=Q.top().second; Q.pop();
            if (vis[u]) continue;
            vis[u]=1,vp.emplace_back(u);
            for (int v:E[u]) --deg[v],Q.emplace(deg[v],v);
            if (Q.top().first>mxp) mxp=Q.top().first,pos=vp.size();
        }
        memset(vis,0,sizeof(vis)),memcpy(deg,odeg,sizeof(deg));
        for (int i=1;i<=n;++i) Q.emplace(deg[i],i);
        while (!Q.empty()) {
            int u=Q.top().second; Q.pop();
            if (vis[u]) continue;
            vis[u]=1,vq.emplace_back(u);
            for (int v:E[u]) vis[v]=1;
        }
        printf("%d",n-pos);
        for (int i=pos;i<n;++i) printf(" %d",vp[i]);
        puts("");
        printf("%lu",vq.size());
        for (int i:vq) printf(" %d",i);
        puts("");

        vp.clear(),vq.clear();
        for (int i=1;i<=n;++i) odeg[i]=0,E[i].clear();
    }
    return 0;
}
最后修改:2021 年 01 月 26 日 08 : 47 AM