Codeforces Round #684 (Div. 2) D. Graph Subset Problem

原题链接:https://codeforces.com/contest/1440/problem/D

题意:

给你一张图,n个点,m条边,给定k,问能否找到下面两种图中任意一种。

  • 找一个大小是k的集合,这k个点两两相连
  • 找一个非空集合,里面每一个点都有至少k个点和他相连。

如果能找到第一种输出格式:

第一行输出2,第二行k个数表示这个k个点,顺序随意输出。

如果可以找到第二种输出格式:

第一行输出1和集合的大小len,第二行len个数,表示这个集合

第一种和第二种集合没有优先级,输出任意一个答案即可。

如果都没有找到则输出-1。

思路:

  • 优先队列存放所有度数小于等于k-1的所有的点
  • 如果度数==k-1,则讨论能否作为第一个的答案,可以则直接break
  • 如果没有找到答案,那么这个点要把他连向的所有的点的度数都-1,并把这个点标记为已经访问过,重复第二个步骤

最后如果中途break了,那么就直接输出第一种答案即可,如果没有,那么判断最后是否还剩下点未被访问,如果有那么就说明这里的每一个点的度数都大于等于k,所以就找到第二种图的答案了,否则输出-1

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int in[maxn];
bool vis[maxn];
struct node{
    int u;
    node(int u=0):u(u){}
    bool operator<(const node&a)const{
        return in[a.u]<in[u];
    }
};
vector<int>G[maxn];
priority_queue<node>que;
void init(int n){
    while(!que.empty()) que.pop();
    for(int i=1;i<=n;i++) {
        in[i] = 0,vis[i] = false;
        G[i].clear();
    }
}
void add(int u,int v){
    G[u].push_back(v);
    G[v].push_back(u);
}
vector<int>a;
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        init(n);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            in[u]++,in[v]++;
//            printf("")
        }
        if(1ll*k*(k-1)>2*m){
            printf("-1\n");
            continue;
        }
        for(int i=1;i<=n;i++) {
//            printf("in[%d]=%d\n",i,in[i]);
            if(in[i]<k) que.push(i);
            sort(G[i].begin(),G[i].end());
        }
        int ok = 0,now = n;
        while(!que.empty()){
            int u = que.top().u;que.pop();
//            printf("u = %d vis[%d]=%d in[%d]=%d\n",u,u,vis[u],u,in[u]);
            if(vis[u]) continue;
            if(in[u]==k-1){
                a.clear();
                int len = G[u].size();
                for(int i=0;i<len;i++){
                    int v = G[u][i];
                    if(vis[v]) continue;
                    a.push_back(v);
                }
                ok = u;
                len = a.size();
                for(int i=0;i<len&&ok;i++){
                    for(int j=i+1;j<len&&ok;j++){
                        int l = a[i],r = a[j];
                        if(!binary_search(G[l].begin(),G[l].end(),r)){
                            ok = 0;
                            break;
                        }
                    }
                }
            }
            if(ok) {
                a.push_back(u);
                break;
            }
            int len = G[u].size();
            for(int i=0;i<len;i++){
                int v = G[u][i];
                if(vis[v]) continue;
                in[v]--;
                if(in[v]<k) que.push(v);
            }
            vis[u] = true;
            now--;
        }
        if(ok){
            printf("2\n");
            for(int i=0;i<k;i++){
                printf("%d ",a[i]);
            }
            printf("\n");
        }
        else if(now){
            printf("1 %d\n",now);
            for(int i=1;i<=n;i++){
                if(vis[i]) continue;
                printf("%d ",i);
            }
            printf("\n");
        }
        else printf("-1\n");
    }
    return 0;
}

 

posted @ 2020-12-04 23:05  Shmilky  阅读(88)  评论(0编辑  收藏  举报