zoukankan      html  css  js  c++  java
  • SDOI2019热闹又尴尬的聚会

    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
    ",p,q);
            printf("%d ",(int)G1.size());
            for(int i = 0;i < (int)G1.size();++i) printf("%d ",G1[i]);printf("
    ");
            printf("%d ",(int)G2.size());
            for(int i = 0;i < (int)G2.size();++i) printf("%d ",G2[i]);printf("
    ");
        }	
        return 0;	
    }
    
  • 相关阅读:
    Encryption (hard) CodeForces
    cf 1163D Mysterious Code (字符串, dp)
    AC日记——大整数的因子 openjudge 1.6 13
    AC日记——计算2的N次方 openjudge 1.6 12
    Ac日记——大整数减法 openjudge 1.6 11
    AC日记——大整数加法 openjudge 1.6 10
    AC日记——组合数问题 落谷 P2822 noip2016day2T1
    AC日记——向量点积计算 openjudge 1.6 09
    AC日记——石头剪刀布 openjudge 1.6 08
    AC日记——有趣的跳跃 openjudge 1.6 07
  • 原文地址:https://www.cnblogs.com/wyxdrqc/p/10847965.html
Copyright © 2011-2022 走看看