由于两者是独立的,我们希望两者的$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 }

[luogu5361]热闹的聚会与尴尬的聚会的更多相关文章

  1. vijos2054 SDOI2019 热闹的聚会与尴尬的聚会

    题目链接 思路 首先观察题目最后的式子\(\lfloor \frac{n}{p + 1} \rfloor \le q\) 并且\(\lfloor \frac{n}{q+1} \rfloor \le p ...

  2. [SDOI2019]热闹又尴尬的聚会 构造,贪心

    [SDOI2019]热闹又尴尬的聚会 链接 luogu loj 思路 第一问贪心?的从小到大删除入度最小的点,入度是动态的,打个标记. 当然不是最大独立集. 第二问第一问的顺序选独立集,不行就不要.选 ...

  3. SDOI2019热闹又尴尬的聚会

    P5361 [SDOI2019]热闹又尴尬的聚会 出题人用脚造数据系列 只要将\(p\)最大的只求出来,\(q\)直接随便rand就能过 真的是 我们说说怎么求最大的\(p\),这个玩意具有很明显的单 ...

  4. 【题解】Luogu P5361 [SDOI2019]热闹又尴尬的聚会

    原题传送门 构造题. 明显p,q都越大越好 我们考虑每次取出度最小的点,加到尴尬聚会的集合中(因为把与它相邻的点全删了,不珂能出现认识的情况),把它自己和与自己相连的点从图上删掉(边也删掉),记下这个 ...

  5. [SDOI2019] 热闹又尴尬的聚会

    热闹度\(p\)子图中最小的度数,尴尬度\(q\)独立集大小,之间的约束 \[ \begin{aligned} \lfloor n/(p+1)\rfloor\le q &\rightarrow ...

  6. [洛谷P5361][SDOI2019]热闹又尴尬的聚会:构造题

    分析 构造方法 (截图自UOJ群) 可以使用std::set维护这个过程,不过据说可以做到\(O(n+m)\).. 正确性证明 题目中的要求等价于\((p+1)(q+1) > n\) 设每次找出 ...

  7. [SDOI2019]热闹又尴尬的聚会(图论+set+构造)

    据说原数据可以让复杂度不满的暴力O(Tn^2)过掉……O(Tn^2)方法类似于codeforces一场div2的E题 有一种比较好的方法:每次找出原图G中度最小的点加入q,然后将相邻的点加入新图G'. ...

  8. SDOI2019 Round2

    这鬼家伙已经咕了好久了-- SDOIR2的题目挺好玩的- 快速查询(???) 不难发现所有的操作都可以通过区间打Tag实现 那么可以维护两个标记\(a,b\)表示序列中的数为\(x\)时实际表示的值是 ...

  9. Solution Set - 《赏竹而格之》

    1.「GXOI / GZOI 2019」「洛谷 P5304」旅行者   Link & Submission.   经典二进制分组,没啥好说的. 2. 「SDOI 2019」「洛谷 P5361」 ...

随机推荐

  1. 现代 C++ 对多线程/并发的支持(上) -- 节选自 C++ 之父的 《A Tour of C++》

    本文翻译自 C++ 之父 Bjarne Stroustrup 的 C++ 之旅(A Tour of C++)一书的第 13 章 Concurrency.用短短数十页,带你一窥现代 C++ 对并发/多线 ...

  2. IDEA Web渲染插件开发(二)— 自定义JsDialog

    <IDEA Web渲染插件开发(一)>中,我们了解到了如何编写一款用于显示网页的插件,所需要的核心知识点就是IDEA插件开发和JCEF,在本文中,我们将继续插件的开发,为该插件的JS Di ...

  3. 教你 4 步搭建弹性可扩展的 WebAPI

    作者 | 萧起  阿里云云原生团队 本文整理自<Serverless 技术公开课>,关注"Serverless"公众号,回复"入门",即可获取 Se ...

  4. 【Ubuntu】VirtualBox 您没有查看“sf_VirtualDisk”的内容所需的权限

    ​ 但是现在发现无法去访问,没有权限: ​ 即使是: crifan@crifan-Ubuntu:~$ sudo chown -R crifan /media/sf_win7_to_ubuntu/ cr ...

  5. 题解 [ZJOI2019]语言

    题目传送门 题目大意 给出一个 \(n\) 个点的树,现在有 \(m\) 次操作,每次可以选择一个链 \(s,t\),,然后这条链上每个点都会增加一个相同属性,问对于每一个点有与它相同属性的有多少个点 ...

  6. MySQL ENGINES 引擎

    引擎 存储引擎是数据库底层软件组织. 数据库管理系统(DBMS)使用数据引擎进行创建.查询.更新和删除数据. 不同的存储引擎提供不同的存储机制.索引技巧.锁定水平等功能. MySQL的核心就是存储引擎 ...

  7. Spring Boot 如何热加载jar实现动态插件?

    一.背景 动态插件化编程是一件很酷的事情,能实现业务功能的 解耦 便于维护,另外也可以提升 可扩展性 随时可以在不停服务器的情况下扩展功能,也具有非常好的 开放性 除了自己的研发人员可以开发功能之外, ...

  8. vue3双向数据绑定原理_demo

    <!DOCTYPE html> <head> <meta charset="UTF-8" /> <meta name="view ...

  9. Java字符串转数字和数字转字符串

    int转String有3种方式 (1)num + "" (2)String.valueOf(num) (3)Integer.toString(num) String转int有2种方 ...

  10. .net Xml加密解密操作

    生成密钥的方法: /// <summary>生成RSA加密 解密的 密钥 /// 生成的key就是 方法EncryptByRSA与DecryptByRSA用的key了 /// </s ...