概述
题目链接
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
1≤t≤105) — 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 1≤n,m,k≤105, k ≤ n k leq n k≤n).
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) (1≤u,v≤n,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 2⋅105.
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⋅(k−1)>m 则一定无解。
大小为
k
k
k 的团和度大于等于
k
k
k 的完全子图只如果存在要找到其中一个即可。
由于因此大小为
k
k
k 的团在度上的要求更宽松一些,因此不妨先判断是否存在大小为
k
k
k 的团。
如果一个点在大小为
k
k
k 的团中,则首先该点的度一定大于等于
k
−
1
k-1
k−1 ,因此可以通过拓扑排序删掉图中度小于
k
−
1
k-1
k−1 的点,剩下的点构成的图中每个点的度大于等于
k
−
1
k-1
k−1。
类似拓扑排序,将度等于
k
−
1
k-1
k−1 (选度最小的,否则会出现条件与后面的操作不相符的情况) 点入队,每次从队列中取出一个元素,若与该点相邻的点度数大于等于
k
−
1
k-1
k−1 的点数量小于
k
−
1
k-1
k−1 时,则该点一定不在团中,因此将该点删掉;若与该点相邻的点度数大于等于
k
−
1
k-1
k−1 的点数量等于
k
−
1
k-1
k−1 时,枚举相邻的
k
−
1
k-1
k−1 个点中任意两个点判断是否连通,从而判断出这
k
−
1
k-1
k−1 个点是否构成完全图。
上面求大小为
k
k
k 的团可能会落下一种情况,即图中每个点的度数都大于
k
−
1
k-1
k−1 ,且存在大小为
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所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复