[luogu5361]热闹的聚会与尴尬的聚会

由于两者是独立的,我们希望两者的$p$和$q$都最大

考虑最大的$p$,先全部邀请,此时要增大$p$显然必须要删去当前度数最小的点,不断删除之后将每一次度数最小值对答案取max即可

对于$q$也即最大独立集,并没有很好的解法,但考虑不断加入一个节点$x$,并删去$x$以及与$x$相邻的节点,重复此过程直至原图为空即得到了一个独立集

每一次贪心选择度数最小的节点$x$,显然$x$的度数一定不超过$p$,换言之每一次至多删去$p+1$个节点,最终要删去所有节点,即有$\lceil\frac{n}{p+1}\rceil\le q$

接下来要证明$\lfloor\frac{n}{q+1}\rfloor\le p$,注意到$\lfloor\frac{n}{q+1}\rfloor\le \lceil\frac{n}{q}\rceil-1$,而根据$\lceil\frac{n}{p+1}\rceil\le q$有$\lceil\frac{n}{q}\rceil\le p+1$,即得证

(用了快读+快输还是TLE了一个点)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 100005
  4 set<pair<int,int> >s;
  5 vector<int>ans;
  6 struct Edge{
  7     int nex,to;
  8 }edge[N<<1];
  9 int E,t,n,m,x,y,a[11],head[N],r[N],rr[N],vis[N];
 10 int read(){
 11     int x=0;
 12     char c=getchar();
 13     while ((c<'0')||(c>'9'))c=getchar();
 14     while ((c>='0')&&(c<='9')){
 15         x=x*10+c-'0';
 16         c=getchar();
 17     }
 18     return x;
 19 }
 20 void write(int x){
 21     a[0]=0;
 22     while (x){
 23         a[++a[0]]=x%10;
 24         x/=10;
 25     }
 26     for(int i=a[0];i;i--)putchar(a[i]+'0');
 27 }
 28 void add(int x,int y){
 29     edge[E].nex=head[x];
 30     edge[E].to=y;
 31     head[x]=E++;
 32 }
 33 int main(){
 34     t=read();
 35     while (t--){
 36         n=read(),m=read();
 37         E=0;
 38         memset(head,-1,sizeof(head));
 39         memset(r,0,sizeof(r));
 40         for(int i=1;i<=m;i++){
 41             x=read(),y=read();
 42             add(x,y);
 43             add(y,x);
 44             r[x]++,r[y]++;
 45         }
 46         memcpy(rr,r,sizeof(r));
 47         s.clear();
 48         memset(vis,0,sizeof(vis));
 49         for(int i=1;i<=n;i++)s.insert(make_pair(r[i],i));
 50         for(int i=1;i<=n;i++){
 51             x=(*s.begin()).second;
 52             s.erase(s.begin());
 53             vis[x]=i;
 54             for(int i=head[x];i!=-1;i=edge[i].nex)
 55                 if (!vis[edge[i].to]){
 56                     s.erase(make_pair(r[edge[i].to],edge[i].to));
 57                     s.insert(make_pair(--r[edge[i].to],edge[i].to));
 58                 }
 59         }
 60         for(int i=1;i<=n;i++)r[0]=max(r[0],r[i]);
 61         for(int i=1;i<=n;i++)
 62             if (r[0]==r[i])x=i;
 63         ans.clear();
 64         for(int i=1;i<=n;i++)
 65             if (vis[i]>=vis[x])ans.push_back(i);
 66         write(ans.size());
 67         putchar(' ');
 68         for(int i=0;i<ans.size();i++){
 69             write(ans[i]);
 70             putchar(' ');
 71         }
 72         putchar('\n');
 73         memcpy(r,rr,sizeof(r));
 74         s.clear();
 75         ans.clear();
 76         memset(vis,0,sizeof(vis));
 77         for(int i=1;i<=n;i++)s.insert(make_pair(r[i],i));
 78         while (!s.empty()){
 79             x=(*s.begin()).second;
 80             s.erase(s.begin());
 81             vis[x]=1;
 82             ans.push_back(x);
 83             for(int i=head[x];i!=-1;i=edge[i].nex)
 84                 if (!vis[edge[i].to]){
 85                     vis[edge[i].to]=1;
 86                     s.erase(make_pair(r[edge[i].to],edge[i].to));
 87                     for(int j=head[edge[i].to];j!=-1;j=edge[j].nex)
 88                         if (!vis[edge[j].to]){
 89                             s.erase(make_pair(r[edge[j].to],edge[j].to));
 90                             s.insert(make_pair(--r[edge[j].to],edge[j].to));
 91                         }
 92                 }
 93         }
 94         write(ans.size());
 95         putchar(' ');
 96         for(int i=0;i<ans.size();i++){
 97             write(ans[i]);
 98             putchar(' ');
 99         }
100         putchar('\n');
101     }
102 }
View Code

 

posted @ 2021-04-08 13:35  PYWBKTDA  阅读(69)  评论(0编辑  收藏  举报