P5361 [SDOI2019]热闹又尴尬的聚会

出题人用脚造数据系列

只要将\(p\)最大的只求出来,\(q\)直接随便rand就能过

真的是

我们说说怎么求最大的\(p\),这个玩意具有很明显的单调性的吧

直接二分一下\(p\)的值,然后将其和他所以相连的所有度数\(>=p\)加进去,

可能最后有一些的点的实际度数\(<=p\)

我们就把他的贡献减掉,再出现再减

每个点只会入队一次

数据太弱,\(q\)直接随机吧

时间复杂度\(O(T(nlogn+rand)\)

#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<ctime>
#include<cmath>
#include<queue>
#include<vector>
#pragma GCC optimize(2)
#define LL long long
#define mk make_pair
#define pii pair<int,int>
using namespace std;
const int N = 1e5 + 3;
const int M = 2e5 + 3;
struct edge{
int to;
int nxt;
}e[M << 2];
int num[N];
int n,m,T,dis,tot;
int head[N],d[N],need[N];
bool book[N],gg[N];
vector <int> G1,G2;
int p,q;
inline char nc(){
#define SIZE 100000
static char buf[SIZE],*p1 = buf+SIZE,*pend = buf+SIZE;
if(p1 == pend){
p1 = buf;pend = buf+fread(buf,1,SIZE,stdin);
if(p1 == pend) return -1;
}
return *p1++;
#undef SIZE
}
inline int read(){
int x = 0;int flag = 0;
char ch = nc();
while(!isdigit(ch)){
if(ch == '-') flag = 1;
ch = nc();
}
while(isdigit(ch)){
x = (x<<1) + (x<<3) + (ch^'0');
ch = nc();
}
if(flag) x = -x;
return x;
}
inline void add(int x,int y){
e[++tot].to = y;
e[tot].nxt = head[x];
head[x] = tot;
}
inline bool check(int mid){
queue <int> qq;
for(int i = 1;i <= n;++i){book[i] = 0;need[i] = 0;gg[i] = 0;}
for(int i = 1;i <= n;++i)
if(d[i] >= mid) qq.push(i);
while(!qq.empty()){
int k = qq.front();qq.pop();
for(int i = head[k];i;i = e[i].nxt){
int y = e[i].to;
if(d[y] < mid) continue;
need[y]++;
}
}
for(int i = 1;i <= n;++i) if(need[i] < mid) qq.push(i);
while(!qq.empty()){
int k = qq.front();qq.pop();
gg[k] = 1;
for(int i = head[k];i;i = e[i].nxt){
int y = e[i].to;
if(d[y] < mid) continue;
need[y]--;
if(need[y] < mid && !gg[y]) gg[y] = 1,qq.push(y);
}
}
bool flag = 0;
// cout << mid << endl;
// for(int i = 1;i <= n;++i) cout << need[i] << " ";cout << endl;
for(int i = 1;i <= n;++i) if(!gg[i] && need[i] >= mid) flag = 1;
if(flag){
G1.clear();
p = mid;
for(int i = 1;i <= n;++i) if(need[i] >= mid) G1.push_back(i);
}
return flag;
}
inline int work(){
int x;
random_shuffle(num + 1,num + n + 1);
int ans = 0;
x = num[1];
for(int i = 1;i <= n;++i) book[i] = 0,gg[i] = 0;
for(int i = head[x];i;i = e[i].nxt){
int y = e[i].to;
book[y] = 1;
}
gg[x] = 1,book[x] = 1;
//ans = 1;
for(int i = 1;i <= n;++i){
if(book[num[i]]) continue;
book[num[i]] = 1;
gg[num[i]] = 1;
ans++;
for(int j = head[num[i]];j;j = e[j].nxt){
int y = e[j].to;
if(book[y]) continue;
book[y] = 1;
}
}
if(ans) ans++;
return ans;
}
int main(){ T = read();
//cout << 1 << endl;
while(T--){
n = read(),m = read();
for(int i = 1;i <= n;++i) num[i] = i;
tot = 0;
for(int i = 1;i <= n;++i) head[i] = 0,d[i] = 0;
for(int i = 1;i <= m;++i){
int x = read(),y = read();
add(x,y);
add(y,x);
d[x]++,d[y]++;
}
//continue;
int l = 1,r = n,ans = 1;
while(l <= r){
int mid = (l + r) >> 1;
// cout << mid << endl;
if(check(mid)) ans = mid,l = mid + 1;
else r = mid - 1;
}
// cout << p <<endl;
// continue;
while(1){//cout << "GG" << endl;
q = work();
if(p >= n / (q + 1) && q >= n / (p + 1)){
G2.clear();
for(int i = 1;i <= n;++i)if(gg[i]) G2.push_back(i);
break;
}
}
// printf("p:%d q:%d\n",p,q);
printf("%d ",(int)G1.size());
for(int i = 0;i < (int)G1.size();++i) printf("%d ",G1[i]);printf("\n");
printf("%d ",(int)G2.size());
for(int i = 0;i < (int)G2.size();++i) printf("%d ",G2[i]);printf("\n");
}
return 0;
}

SDOI2019热闹又尴尬的聚会的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

    由于两者是独立的,我们希望两者的$p$和$q$都最大 考虑最大的$p$,先全部邀请,此时要增大$p$显然必须要删去当前度数最小的点,不断删除之后将每一次度数最小值对答案取max即可 对于$q$也即最大 ...

  8. SDOI2019 Round2

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

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

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

随机推荐

  1. Java程序中如何使用事物

    在java操作数据库是,为了保证数据的一致性,比如转账操作,从一个账户减掉10元,在另一个账户加上10元. 在类中定义的成员属性(变量)不用赋初值,但在函数里头定义的变量就一定要赋初值. packag ...

  2. Symmetric Tree 深度优先搜索

    Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For e ...

  3. NEFU 118 n!后面有多少个0【数论】

    http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=118 求n!后面有多少个0(1<=n<=1000000000) ...

  4. Linux 下的python操作redis

    python操作redis   Redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).se ...

  5. 2019-4-29-dotnet-通过-WMI-获取系统安装软件

    title author date CreateTime categories dotnet 通过 WMI 获取系统安装软件 lindexi 2019-04-29 12:18:59 +0800 201 ...

  6. python 函数定义与调用时,不定长参数的传入

  7. hihocoder 1586 ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛-题目9 : Minimum【线段树】

    https://hihocoder.com/problemset/problem/1586 线段树操作,原来题并不难..... 当时忽略了一个重要问题,就是ax*ay要最小时,x.y可以相等,那就简单 ...

  8. @总结 - 1@ 多项式乘法 —— FFT

    目录 @0 - 参考资料@ @1 - 一些概念@ @2 - 傅里叶正变换@ @3 - 傅里叶逆变换@ @4 - 迭代实现 FFT@ @5 - 参考代码实现@ @6 - 快速数论变换 NTT@ @7 - ...

  9. oracle函数 current_date

    [功能]:返回当前会话时区中的当前日期 [参数]:没有参数,没有括号 [返回]:日期 [示例]select current_date from dual; 返回:2008-11-14

  10. HSV 和 HLS颜色空间

    颜色空间 颜色空间是特定的颜色组织:它提供了将颜色分类,并以数字图像表示的方法. RGB 是红绿蓝颜色空间.你可以将其视为 3D 空间,在这种情况下是立方体,其中任何颜色都可以用 R.G 和 B 值的 ...