ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2020-06-12 11:56:13  阅读:252  来源: 互联网

标签:cnt int leq 尴尬 聚会 SDOI2019 sizeof define


题意:

你有n个好友,他们之间有m对关系$(u,v)$表示u和v互相认识,认识没有传递性。

现在你想组织一场热闹的聚会和一场尴尬的聚会,定义如下:

  • 一场热闹度为p的聚会请来了任意多位好友,对于每一位到场的好友来说都有至少p位他认识的好友也参加了聚会,且至少对于一位到场的好友来说现场恰好有p位他认识的好友;
  • 一场尴尬度为q的聚会请来了恰好q位好友,且他们两两互不认识。

这两场聚会之间没有任何联系。

你希望p和q满足$\lfloor \frac{n}{p+1}\rfloor \leq q$且$\lfloor \frac{n}{q+1}\rfloor \leq p$,求一种合法方案。

$T\leq 32,n\leq 10000,m\leq 10^{5}$。

 

题解:

首先发现对于任意p/q,q/p越大越优,所以原问题可以拆成求最大的p和最大的q。

考虑求最大的p,显然可以依次尝试删除图中度数最小的点,尽管删除点数越多答案不一定越优,但记录最大答案及其删除个数即可。

考虑求最大的q,贪心的想法是依次取图中度数最小的点,并删除它和所有与它相邻的点。

但显然这样求出的并不是最大独立集。因为求一般图最大独立集是个NP问题。

不过,我们本身要求的并不是最大的q,而是任意一个满足$\lfloor \frac{n}{p+1}\rfloor \leq q$且$\lfloor \frac{n}{q+1}\rfloor \leq p$的q,所以有一个奇妙的结论:这样贪心是100%正确的。

证明:考虑p算法的过程,我们每次删除的点的度数一定$\leq p$。

而q算法删的点的度数比p只少不多,也就是说对于q中每次操作至多会删掉p+1个点。

那么显然q算法至少会运行$\lceil \frac{n}{p+1}\rceil$次,这也对应着该算法求出的q的下界。

于是求出的p和q一定满足题目中的限制条件($(p+1)(q+1)>n$时两个条件均满足),证毕。

复杂度$O(T(n+m)logn)$(大概吧),需要稍加优化。

(也许运行q算法时直接删点不更新边权也是对的,但我并不想证明)

 

套路:

  • 在有某些限制条件时瞎蒙一个贪心很可能是对的;
  • 构造题可以考虑将若干个限制条件合并成一个较宽松的限制条件,一般很少有人喜欢把下界卡死(大概吧)。

 

代码:

#include<bits/stdc++.h>
#define maxn 10005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long
#define mp make_pair
#define rint register int
#define debug(x) cerr<<#x<<": "<<x<<endl
#define fgx cerr<<"--------------"<<endl
#define dgx cerr<<"=============="<<endl

using namespace std;
int to[maxm],nxt[maxm],hd[maxn],vis[maxn],cnt;
int A[maxn],B[maxn],deg[maxn],D[maxn];
priority_queue<pair<int,int> > Q;
map<pair<int,int>,int> M;

inline int read(){
    int x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}

inline void addedge(int u,int v){
    to[++cnt]=v,nxt[cnt]=hd[u],hd[u]=cnt;
    to[++cnt]=u,nxt[cnt]=hd[v],hd[v]=cnt;
}

int main(){
    int T=read();
    while(T--){
        memset(A,0,sizeof(A));
        memset(B,0,sizeof(B));
        memset(hd,0,sizeof(hd));
        memset(deg,0,sizeof(deg));
        memset(vis,0,sizeof(vis));
        M.clear(),cnt=0;
        while(!Q.empty()) Q.pop();
        int n=read(),m=read();
        for(int i=1;i<=m;i++){
            int u=read(),v=read(); if(u>v) swap(u,v);
            if(M[mp(u,v)]) continue;
            else addedge(u,v),M[mp(u,v)]=1,deg[u]++,deg[v]++;
        }
        memcpy(D,deg,sizeof(deg));
        for(int i=1;i<=n;i++) Q.push(mp(-deg[i],i));
        int ans=0,endpos=0;
        while(!Q.empty()){
            int u=Q.top().second,d=-Q.top().first; 
            Q.pop(); if(vis[u]) continue;
            vis[u]=1,A[++A[0]]=u;
            if(ans<-Q.top().first)
                ans=-Q.top().first,endpos=A[0];
            for(int i=hd[u];i;i=nxt[i])
                if(!vis[to[i]]) 
                    Q.push(mp(-(--deg[to[i]]),to[i]));
            
        }
        memcpy(deg,D,sizeof(D));
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++) Q.push(mp(-deg[i],i));
        while(!Q.empty()){
            int u=Q.top().second,d=-Q.top().first; 
            Q.pop(); if(vis[u]) continue;
            vis[u]=1,B[++B[0]]=u;
            for(int i=hd[u];i;i=nxt[i]){
                int v=to[i];
                if(vis[v]) continue;
                vis[v]=1;
                for(int j=hd[v];j;j=nxt[j]){
                    int w=to[j];
                    if(vis[w]) continue;
                    Q.push(mp(-(--deg[w]),w));
                }
            }
        }
        printf("%d",n-endpos);
        for(int i=endpos+1;i<=n;i++) printf(" %d",A[i]);
        printf("\n");
        printf("%d",B[0]);
        for(int i=1;i<=B[0];i++) printf(" %d",B[i]);
        printf("\n");
    }
    return 0;
}
热闹的聚会与尴尬的聚会

 

标签:cnt,int,leq,尴尬,聚会,SDOI2019,sizeof,define
来源: https://www.cnblogs.com/YSFAC/p/13098550.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有