zoukankan      html  css  js  c++  java
  • D. Graph Subset Problem 思维 + 优先队列

    D. Graph Subset Problem 思维 + 优先队列

    题目大意:

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

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

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

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

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

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

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

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

    题解:

    优先队列解决

    思路很简单,第二个图的找法:

    • 首先先把所有小于k条边的删去,删去的同时,他连向的点的入度都-1
    • 一种重复第一个步骤,最后如果剩下一个非空集合就是答案

    第二个图:

    • 先把所有小于k-1的边都删去,删去的同时,他连向的点入度都-1
    • 如果存在一个点度数是k-1,那么就要讨论这个点能否作为答案,k*k的判断

    写起来很麻烦,写了一个线段树。。。然后wa了

    看到刘雨小姐姐的一个挺简洁的写法。

    • 优先队列存放所有度数小于等于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
    ");
                continue;
            }
            for(int i=1;i<=n;i++) {
    //            printf("in[%d]=%d
    ",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
    ",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
    ");
                for(int i=0;i<k;i++){
                    printf("%d ",a[i]);
                }
                printf("
    ");
            }
            else if(now){
                printf("1 %d
    ",now);
                for(int i=1;i<=n;i++){
                    if(vis[i]) continue;
                    printf("%d ",i);
                }
                printf("
    ");
            }
            else printf("-1
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    Android Studio快捷键
    Eclipse常用快捷键
    沉浸式状态栏
    JAVA起名规范
    c语言求数组长度
    自定义checkbox风格
    退出所有应用,监控打开了什么活动
    android权限大全
    广播接收者Receiver
    ImageView的常用属性
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/14008209.html
Copyright © 2011-2022 走看看