我是靠谱客的博主 真实小懒虫,最近开发中收集的这篇文章主要介绍Codeforces Round #684 (Div. 2) Graph Subset Problem,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目链接
You are given an undirected graph with n n n vertices and m m m edges. Also, you are given an integer k k k.

Find either a clique of size k k k or a non-empty subset of vertices such that each vertex of this subset has at least k k k neighbors in the subset. If there are no such cliques and subsets report about it.

A subset of vertices is called a clique of size k k k if its size is k k k and there exists an edge between every two vertices from the subset. A vertex is called a neighbor of the other vertex if there exists an edge between them.

Input
The first line contains a single integer t t t ( 1 ≤ t ≤ 1 0 5 1 leq t leq 10^5 1t105) — the number of test cases. The next lines contain descriptions of test cases.

The first line of the description of each test case contains three integers n n n, m m m, k k k ( 1 ≤ n , m , k ≤ 1 0 5 1 leq n, m, k leq 10^5 1n,m,k105, k ≤ n k leq n kn).

Each of the next m m m lines contains two integers u , v u, v u,v ( 1 ≤ u , v ≤ n , u ≠ v ) (1 leq u, v leq n, u neq v) (1u,vn,u=v), denoting an edge between vertices u u u and v v v.

It is guaranteed that there are no self-loops or multiple edges. It is guaranteed that the sum of n n n for all test cases and the sum of m m m for all test cases does not exceed 2 ⋅ 1 0 5 2 cdot 10^5 2105.

Output
For each test case:

If you found a subset of vertices such that each vertex of this subset has at least k k k neighbors in the subset in the first line output 1 1 1 and the size of the subset. On the second line output the vertices of the subset in any order.

If you found a clique of size k k k then in the first line output 2 2 2 and in the second line output the vertices of the clique in any order.

If there are no required subsets and cliques print − 1 -1 1.

If there exists multiple possible answers you can print any of them.

Example
input

3
5 9 4
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
10 15 3
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
4 5 4
1 2
2 3
3 4
4 1
1 3

output

2
4 1 2 3 
1 10
1 2 3 4 5 6 7 8 9 10 
-1

Note
In the first test case: the subset { 1 , 2 , 3 , 4 } {1, 2, 3, 4} {1,2,3,4} is a clique of size 4 4 4.

In the second test case: degree of each vertex in the original graph is at least 3 3 3. So the set of all vertices is a correct answer.

In the third test case: there are no cliques of size 4 4 4 or required subsets, so the answer is − 1 -1 1.
首先,如果 k ⋅ ( k − 1 ) 2 > m frac{kcdot(k-1)}{2}>m 2k(k1)>m 则一定无解。
大小为 k k k 的团和度大于等于 k k k 的完全子图只如果存在要找到其中一个即可。
由于因此大小为 k k k 的团在度上的要求更宽松一些,因此不妨先判断是否存在大小为 k k k 的团。
如果一个点在大小为 k k k 的团中,则首先该点的度一定大于等于 k − 1 k-1 k1 ,因此可以通过拓扑排序删掉图中度小于 k − 1 k-1 k1 的点,剩下的点构成的图中每个点的度大于等于 k − 1 k-1 k1
类似拓扑排序,将度等于 k − 1 k-1 k1 (选度最小的,否则会出现条件与后面的操作不相符的情况) 点入队,每次从队列中取出一个元素,若与该点相邻的点度数大于等于 k − 1 k-1 k1 的点数量小于 k − 1 k-1 k1 时,则该点一定不在团中,因此将该点删掉;若与该点相邻的点度数大于等于 k − 1 k-1 k1 的点数量等于 k − 1 k-1 k1 时,枚举相邻的 k − 1 k-1 k1 个点中任意两个点判断是否连通,从而判断出这 k − 1 k-1 k1 个点是否构成完全图。
上面求大小为 k k k 的团可能会落下一种情况,即图中每个点的度数都大于 k − 1 k-1 k1 ,且存在大小为 k k k 的团,而这种框符合每个点的度数至少为 k k k 的完全子图。
因此如果没找出大小为 k k k 的团,则继续找每个点的度数至少为 k k k 的完全子图即可。方法同样类似拓扑排序,将度数小于 k k k 点都删掉,如果剩下点,则找到一个连通的点集即为答案,否则输出 − 1 -1 1

#include<bits/stdc++.h>

using namespace std;
const int N = 1e5 + 10;
int T, n, m, k, deg[N];
bool v[N];
queue<int> q;
vector<int> G[N], tmp;

int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d%d", &n, &m, &k);
        memset(deg, 0, sizeof(int) * (n + 1));
        for (int i = 1; i <= n; ++i)G[i].clear();
        for (int i = 1; i <= m; ++i) {
            int x, y;
            scanf("%d%d", &x, &y);
            G[x].push_back(y), G[y].push_back(x);
            deg[x]++, deg[y]++;
        }
        if (1ll * k * (k - 1) / 2 > m) {
            puts("-1");
            continue;
        }
        for (int i = 1; i <= n; ++i) {
            sort(G[i].begin(), G[i].end());
            if (deg[i] < k - 1)q.push(i);
        }
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            if (!deg[x])continue;
            deg[x] = 0;
            for (int y:G[x])
                if (deg[y] && --deg[y] < k - 1)q.push(y);
        }
        bool suc = false;
        for (int i = 1; i <= n; ++i)if (deg[i] == k - 1)q.push(i);
        while (!q.empty()) {
            int x = q.front();
            q.pop(), tmp.clear();
            for (int y:G[x])if (deg[y] >= k - 1)tmp.push_back(y);
            if (tmp.size() < k - 1) {
                for (int y:tmp) if (--deg[y] == k - 1)q.push(y);
                deg[x] = 0;
                continue;
            }
            bool flag = true;
            for (int i = 0; i <= k - 3; ++i) {
                for (int j = i + 1; j <= k - 2; ++j)
                    if (!binary_search(G[tmp[i]].begin(), G[tmp[i]].end(), tmp[j])) {
                        flag = false;
                        break;
                    }
                if (!flag)break;
            }
            if (flag) {
                puts("2");
                printf("%d", x);
                for (int y:tmp)
                    printf(" %d", y);
                puts("");
                suc = true;
                while (!q.empty())q.pop();
                break;
            } else {
                for (int y:tmp) if (--deg[y] == k - 1)q.push(y);
                deg[x] = 0;
            }
        }
        if (suc)continue;
        for (int i = 1; i <= n; ++i)if (deg[i] && deg[i] < k)q.push(i);
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            if (!deg[x])continue;
            deg[x] = 0;
            for (int y:G[x])if (deg[y] && --deg[y] < k)q.push(y);
        }
        for (int i = 1; i <= n; ++i)
            if (deg[i] >= k) {
                suc = true;
                tmp.clear();
                q.push(i), v[i] = true;
                while (!q.empty()) {
                    int x = q.front();
                    tmp.push_back(x);
                    q.pop();
                    for (int y:G[x]) {
                        if (v[y] || deg[y] < k)continue;
                        v[y] = true, q.push(y);
                    }
                }
                printf("1 %dn", tmp.size());
                for (int x:tmp)printf("%d ", x), v[x] = false;
                puts("");
                break;
            }
        if (!suc)puts("-1");
    }
    return 0;
}

最后

以上就是真实小懒虫为你收集整理的Codeforces Round #684 (Div. 2) Graph Subset Problem的全部内容,希望文章能够帮你解决Codeforces Round #684 (Div. 2) Graph Subset Problem所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(30)

评论列表共有 0 条评论

立即
投稿
返回
顶部