zoukankan      html  css  js  c++  java
  • 【思维】dfs树/求最小环——cf 1364D

    这题的强化版 1325F

    题目里很友好的给了一个结论:对于任何一张n个点的无向图,任何一个k<=n,图中要么有大小不超过k的环,要么有大小为ceil(k/2)的独立集

    证明很简单:

      我们先定义单元环:环上的点的度数都为2

      对于任意一个单元环,其大小如果超过k,那么必有>=ceil(k/2)的独立集

    然后考虑如何求任意一个这样的单元环:bfs时只要碰到的第一个环就是单元环,我们把这个单元环取出来判一下就行

    /*
    图中的最小环,如果环大小>k,说明环中必定存在ceil(k/2)的独立集 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define N 200005
    
    int n,m,k,pre[N],vis[N];
    vector<int>G[N],cir; 
    
    void reverse(vector<int>&v){
        int i=0,j=v.size()-1;
        while(i<j)
            swap(v[i],v[j]),++i,--j;
    }
    
    void bfs(){
        for(int i=1;i<=n;i++)vis[i]=-1;
        queue<int>q;
        q.push(1);
        vis[1]=1;pre[1]=1;
        while(q.size()){
            int u=q.front();q.pop();
            for(auto v:G[u])if(v!=pre[u]){
                if(vis[v]==-1){
                    vis[v]=vis[u]^1;
                    q.push(v);
                    pre[v]=u;
                }
                else {//出现环了 
                    vector<int>v1,v2;
                    int t=v;
                    v1.push_back(t);
                    while(pre[t]!=t)
                        v1.push_back(pre[t]),t=pre[t];
                    t=u;
                    v2.push_back(t);
                    while(pre[t]!=t)
                        v2.push_back(pre[t]),t=pre[t];
                    
                    reverse(v1);
                    reverse(v2);
                    
                    //for(auto x:v2)cout<<x<<" ";
                    
                    int i;
                    vector<int>s;
                    for(i=0;i<v1.size()&&i<v2.size();i++)
                        if(v1[i]!=v2[i])break;
                    i--;
                    for(int j=i;j<v1.size();j++)
                        s.push_back(v1[j]);
                    for(int j=v2.size()-1;j>i;j--)
                        s.push_back(v2[j]);
                    if(s.size()<=k){//环<=k 
                        cout<<2<<'
    '<<s.size()<<'
    ';
                        for(auto x:s)cout<<x<<' ';
                        return;
                    }
                    
                    vector<int>s1,s0;//独立集 
                    for(auto x:s){
                        if(vis[x]==0)s0.push_back(x);
                        else s1.push_back(x);
                    }                
                    if(s1.size()>s0.size())swap(s1,s0);
                    cout<<1<<"
    ";
                    for(int i=0;i<ceil(1.0*k/2);i++)
                        cout<<s1[i]<<" ";
                    return; 
                }
            }
        }
        //是个无环图输出独立集即可 
        vector<int>s1,s0;
        for(int x=1;x<=n;x++){
            if(vis[x]==0)s0.push_back(x);
            else s1.push_back(x);
        }
        if(s1.size()<s0.size())swap(s1,s0);
        cout<<1<<"
    ";
        for(int i=0;i<ceil(1.0*k/2);i++)
            cout<<s1[i]<<" ";
        return;      
    }
    
    int main(){
        cin>>n>>m>>k;
        for(int i=1;i<=m;i++){
            int u,v;scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        bfs();
    }
  • 相关阅读:
    ZOJ 3556
    ZOJ 2836
    HDU 2841
    HDU 4135
    POJ 3695
    POJ 2773
    HDU 4407
    HDU 1796
    ZOJ 3688
    ZOJ 3687
  • 原文地址:https://www.cnblogs.com/zsben991126/p/13138191.html
Copyright © 2011-2022 走看看