• Codeforces 1037E Trips【图论】【dfs】


    这道题从看到到做出来有两周吧,一直头铁没有看题解,有一天走路的时候突然就想懂了。有点爽!

    该题的子问题是给一个图,让找其中一个子图使得子图中的每个节点度都大于等于k。怎么解决?

    把这个图里面小于k个度的结点都删掉不就行了,注意这里要用dfs,因为删除u结点后,可能导致v结点的度也不到k了(为了避免重复删除建了一个erase数组)。想到这个的话就差不多做出来了

    肯定能想到反向回答问题,因为删边好解决。把那两个点的度都减一,如果小于k就删除掉。【这里删边我用了map,感觉很神器,因为直接按下标就能删了】

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<algorithm>
    #include<vector>
    #define INF 2e9
    using namespace std;
    
    map<int,bool> mp[200005];
    vector<int> ans;
    int u[200005],v[200005],degree[200005],k;
    int erase[200005];
    
    int delet(int u){//返回删除u这个人,所产生的总效应(导致一共要删多少人) 
        int cnt=1;//已经删了u这个人 
        erase[u]=1;
        map<int,bool>::iterator it=mp[u].begin();
        for(;it!=mp[u].end();it++){
            int v=it->first;
            if( !erase[v] ){//只有当v没被删除的时候才需要考虑 
                degree[v]--;
                if( degree[v]<k ) cnt+=delet(v); 
            }
        }
        return cnt;
    }
    
    int main(){
        ios::sync_with_stdio(false);
        int n,m; cin>>n>>m>>k;
        for(int i=1;i<=m;i++){
            cin>>u[i]>>v[i];
            degree[ u[i] ]++; degree[ v[i] ]++;
            mp[ u[i] ][ v[i] ]=1;
            mp[ v[i] ][ u[i] ]=1;
        }
        
        int count=n;
    //    cout<<count<<endl;
        for(int i=1;i<=n;i++){//
            if( !erase[i] && degree[i]<k ) {
                count-=delet(i);
            //    cout<<i<<" "<<count<<endl;
            }    
        }
    //    cout<<"!!!"<<endl;
        for(int i=m;i>=1;i--){
        //    cout<<count<<endl;
            ans.push_back( count );
            if( erase[ u[i] ] || erase[ v[i] ] ) continue;
        //    cout<<u[i]<<" "<<v[i]<<" "<<degree[ u[i] ]<<" "<<degree[ v[i] ]<<endl;
            degree[ u[i] ]--; degree[ v[i] ]--; 
            mp[ u[i] ].erase( v[i] ); mp[ v[i] ].erase( u[i] );
            if( degree[ u[i] ]<k ) count-=delet( u[i] );
            if( !erase[ v[i] ] && degree[ v[i] ]<k ) count-=delet( v[i] );//删除u[i]可能导致把v[i]删除掉 
            
        }
        
        reverse(ans.begin(),ans.end());
        for(int i=0;i<ans.size();i++) cout<<ans[i]<<endl;
        
        return 0;    
    }
  • 相关阅读:
    loadOnStartup = 1
    TP复习8
    TP复习7
    TP复习6
    TP复习5
    TP复习4
    TP复习3
    TP复习2
    TP复习
    document.createElement("A");
  • 原文地址:https://www.cnblogs.com/ZhenghangHu/p/9689311.html
Copyright © 2020-2023  润新知