• 【洛谷5361】[SDOI2019] 热闹的聚会与尴尬的聚会(联合构造题)


    点此看题面

    • 给定一张(n)个点(m)条边的图。
    • 要求构造两个子图(可以有重复点),第一个子图中有任意多个点且所有点度数大于等于(p),第二个子图有(q)个点且是一个独立集。
    • (p,q)由你自己决定,只需满足(lfloorfrac n{p+1} floorle q)(lfloorfrac n{q+1} floorle p)
    • 数据组数(le32)(nle10^4,mle10^5)

    联合构造题

    要单独构造一个最大独立集显然是不太可能的事。

    分析(lfloorfrac n{p+1} floorle qLeftrightarrowfrac n{p+1}<q+1Leftrightarrow(p+1)(q+1)>n),而另一个条件也同样可以转化成这个式子。

    那么,就容易想到把这两个东西合起来一起构造。

    具体地,对于第一个子图,我们可以直接枚举最小的度数(p),那么所有比这个度数小的点都将被删掉。

    每删掉一个点,我们都把它尝试加入独立集,由于这个点度数肯定小于最终的(p),即便它被加入了独立集,也只会让小于(p)个数无法再加入独立集。

    这么一看,显然可以满足((p+1)(q+1)>n),于是这道题就做完了。

    代码:(O(Tm))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 10000
    #define M 100000
    #define Pr pair<int,int>
    #define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
    using namespace std;
    int n,m,A[N+5],B[N+5],ee,lnk[N+5];struct edge {int to,nxt;}e[2*M+5];
    int d[N+5],nB[N+5],vis[N+5];queue<int> q[N+5];
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
    	int OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
    	I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    	Tp I void write(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc(' ');}
    	I void writeln() {pc('
    ');}
    }using namespace FastIO;
    int main()
    {
    	RI Tt,i,x,y,k,p,a,b,ct;read(Tt);W(Tt--)
    	{
    		for(read(n,m),ee=0,i=1;i<=n;++i) {lnk[i]=d[i]=nB[i]=0,vis[i]=-1;W(!q[i].empty()) q[i].pop();}//清空
    		for(i=1;i<=m;++i) read(x,y),add(x,y),add(y,x),++d[x],++d[y];//初始图,统计每个点度数
    		for(i=1;i<=n;++i) q[d[i]].push(i);for(a=b=p=0;p<=n&&(p+1)*(b+1)<=n;++p) W(!q[p].empty())//枚举最小度数,然后删去最小度数的点
    		{
    			if(k=q[p].front(),q[p].pop(),~vis[k]) continue;vis[k]=p,!nB[k]&&(B[++b]=k);//已访问过的删去,然后尝试加入独立集
    			for(i=lnk[k];i;i=e[i].nxt) !~vis[e[i].to]&&
    				(!nB[k]&&(nB[e[i].to]=k),d[e[i].to]>p&&(q[--d[e[i].to]].push(e[i].to),0));//更新相连点度数,如果k在独立集中还要让相连点无法进入
    		}
    		for(i=1;i<=n;++i) !~vis[i]&&(A[++a]=i);//没被访问到的点度数≥最小度数,作为第一子图中的点
    		for(write(a),i=1;i<=a;++i) write(A[i]);writeln();for(write(b),i=1;i<=b;++i) write(B[i]);writeln();//输出构造方案
    	}return clear(),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    UFLDL深度学习笔记 (四)用于分类的深度网络
    UFLDL深度学习笔记 (三)无监督特征学习
    UFLDL深度学习笔记 (二)SoftMax 回归(矩阵化推导)
    UFLDL深度学习笔记 (一)反向传播与稀疏自编码
    【2016内推】计算机找工作面经
    关于最优化中的若干问题
    关于extern "C" 的用法
    浅谈多核CPU、多线程、多进程
    并发与并行
    多进程与多线程
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu5361.html
Copyright © 2020-2023  润新知