CF1439B Graph Subset Problem

https://www.luogu.com.cn/problem/CF1439B

k k k显然 ≤ n \le \sqrt{n} n

首先度数 < k − 1 < k-1 <k1的点及其相连的边是没用用的

所以可以先把这些点扔掉,剩下的点度数一定是 ≥ k − 1 \ge k-1 k1

如果不存在度数为 k − 1 k-1 k1的点,那么吧其中一个联通块拿出来就是第一类的答案

否则枚举 k − 1 k-1 k1度点,然后 k 2 k^2 k2枚举它的所有邻居,用map判断是否有连边,用unordered_map可以去掉log

因为这样的点一定不会超过 n / k n/k n/k个,所以时间复杂度是 n / k ∗ k 2 = O ( n k ) ≤ O ( n n ) n/k*k^2=O(nk)\le O(n\sqrt{n}) n/kk2=O(nk)O(nn )

#include<bits/stdc++.h>
#define N 400050
using namespace std;
inline int read() {
    int x = 0; char ch = getchar();
    for(; ch < '0' || ch > '9'; ) ch = getchar();
    for(; ch >= '0' && ch <= '9'; ) x = (x << 3) + (x <<1) + (ch - '0'), ch = getchar();
    return x;
}
int n, m, k, vis[N], in[N];
unordered_map<int, int> mp[N];
vector<int> g[N];
queue<int> q;
int check(int u) {
    // if(u == 23 && k == 3) {
    //     printf("** %d %d      %d %d %d   %d %d\n", u, in[u], n, m, k, in[54], in[41]);
    //  for(int i = 1; i <= n; i ++) printf("%d ", in[i]); printf("\n");  
    // }
    // printf("** %d %d\n", u, in[u]);
    // for(int i = 1; i <= n; i ++) printf("%d ", in[i]); printf("\n");
    if(in[u] != k - 1) return 0;
    if(1ll * k * (k - 1) / 2 > m) return 0;
    for(auto x : g[u]) if(!vis[x]) {
        for(auto y : g[u]) if(!vis[y]) {
            if(x == y) continue;
            if(!mp[x][y]) return 0;
        }
    }
    return 1;
}
void solve() {
    n = read(), m = read(), k = read();
    for(int i = 1; i <= n; i ++) {
        vis[i] = 0, in[i] = 0, mp[i].clear();
        vector<int> ls; ls.clear(); g[i].swap(ls);
    }
    for(int i = 1; i <= m; i ++) {
        int u, v;
        u = read(), v = read();
        in[u] ++, in[v] ++;
        g[u].push_back(v), g[v].push_back(u);
        mp[u][v] = mp[v][u] = 1;
    }

    while(q.size()) q.pop();
    for(int i = 1; i <= n; i ++) if(in[i] < k) {
        q.push(i); 
    }

    while(q.size()) {
        int u = q.front(); q.pop();
     //   printf("** %d ** ", u);
        if(vis[u]) continue;
        if(check(u)) {
            printf("2\n");
            printf("%d ", u);
            for(int x : g[u]) if(!vis[x]) printf("%d ", x); printf("\n");
            return ;
        }
        vis[u] = 1;
        for(int v : g[u]) {
            if(vis[v]) continue;
            in[v] --; 
            if(in[v] < k) {
                q.push(v);
            } 
        }
    }

    int f = 0;
    for(int i = 1; i <= n; i ++) if(!vis[i]) {
        f = 1;
       // printf("* %d %d\n", i, in[i]);
        break;
    }
    if(!f) {
        printf("-1\n");
        return ;
    }

    //for(int i = 1; i <= n; i ++) printf("%d ", in[i]); printf("     %d\n", f);
    if(f == 1) {
        int gs = 0;
        for(int i = 1; i <= n; i ++) gs += (in[i] >= k);
        printf("1 %d\n", gs);
        for(int i = 1; i <= n; i ++) if(in[i] >= k) printf("%d ", i); printf("\n");
        return ;
    }
}
int t;
int main() {
    t = read();
    while(t --) solve();
    return 0;
}
/*
1
10 15 1
1 2
2 3
3 4
4 5
5 1
1 7
2 8
3 9
4 10
5 6
7 10
10 8
8 6
6 9
9 7
*/
posted @ 2021-12-04 08:12  lahlah  阅读(27)  评论(0编辑  收藏  举报