• LOJ #3113. 「SDOI2019」热闹的聚会与尴尬的聚会 贪心+随机化


    我不明白这道题第二问到底在说啥......   

    第一问比较简单,直接用 set 来贪心就行了.  

    然后我感觉第二问就是求一个最大独立集就行.  

    套路:都 0202 年了,看到最优化就要上随机化呀!!   

    code: 

    #include <bits/stdc++.h>   
    #define N 10008  
    #define M 100008      
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std; 
    int n,m,tot; 
    int hd[N],to[M<<1],nex[M<<1],edges;
    int du[N],ori[N],del[N],vis[N],q[N],arr[N],in[N],brr[N];                    
    inline void add(int u,int v) 
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;  
    }
    inline void clr_graph() 
    {
        for(int i=0;i<=n;++i)    
            hd[i]=0;    
        for(int i=0;i<=edges;++i)   
            to[i]=nex[i]=0;   
        edges=0;  
    }          
    struct node {
        int u,deg;  
        node(int u=0,int deg=0):u(u),deg(deg){}  
        bool operator<(const node b) const { return deg==b.deg?u<b.u:deg<b.deg; }    
    };   
    set<node>se;   
    set<node>::iterator it;          
    void dfs(int x) 
    {
        vis[x]=1,q[++tot]=x;   
        for(int i=hd[x];i;i=nex[i]) 
        {
            int y=to[i]; 
            if(vis[y]||del[y]) continue;   
            dfs(y);  
        }
    }           
    inline int solve_1() 
    {
        scanf("%d%d",&n,&m);   
        for(int i=1;i<=m;++i) 
        {   
            int x,y;  
            scanf("%d%d",&x,&y),add(x,y),add(y,x);
            ++du[x],++du[y];    
            ++ori[x],++ori[y];   
        }                      
        for(int i=1;i<=n;++i) { 
            se.insert(node(i,du[i]));      
        }   
        int ans=0,id=0;   
        for(int i=1;i<=n;++i) 
        { 
            it=se.begin();     
            int u=(*it).u;             
            if(du[u]>ans) ans=du[u],id=u;                     
            for(int j=hd[u];j;j=nex[j]) 
            {
                int y=to[j];        
                if(del[y]) continue;   
                se.erase(node(y,du[y]));   
                --du[y];    
                se.insert(node(y,du[y]));  
            }
            se.erase(node(u,du[u])),del[u]=1;                
        }            
    
        for(int i=1;i<=n;++i) del[i]=0;    
        se.clear();   
        for(int i=1;i<=n;++i) du[i]=ori[i];  
        for(int i=1;i<=n;++i) se.insert(node(i,du[i]));  
        for(int i=1;i<=n;++i) 
        {
            it=se.begin();     
            int u=(*it).u;             
            if(u==id) break;            
            for(int j=hd[u];j;j=nex[j]) 
            {
                int y=to[j];        
                if(del[y]) continue;   
                se.erase(node(y,du[y]));   
                --du[y];    
                se.insert(node(y,du[y]));  
            }
            se.erase(node(u,du[u])),del[u]=1;                
        } 
        
        dfs(id);  
        printf("%d ",tot);  
        for(int i=1;i<=tot;++i) printf("%d ",q[i]);  
        printf("
    ");      
        tot=0; 
        return ans;  
        // 求出最佳解                                    
    
    }
    void solve_2(int p) 
    {
        for(int i=1;i<=n;++i)  arr[i]=i;     
        int ans=0; 
        for(int T=1;T<=10;++T) 
        {
            random_shuffle(arr+1,arr+1+n);       
            int size=0;  
            for(int j=1;j<=n;++j) 
            {
                int u=arr[j],flag=0;  
                for(int k=hd[u];k;k=nex[k]) 
                {
                    int y=to[k];  
                    if(in[y]==T) { flag=1; break; }   
                }    
                if(!flag) in[u]=T,++size;   
            }   
            if(size>ans) 
            { 
                ans=size;  
                for(int i=1;i<=n;++i) brr[i]=arr[i];     
            }
        }    
        printf("%d ",ans);        
        for(int i=1;i<=n;++i) 
        {
            int u=brr[i],flag=0; 
            for(int j=hd[u];j;j=nex[j]) 
            {
                int y=to[j];   
                if(in[y]==-1)  { flag=1; break; }    
            }
            if(!flag) in[u]=-1,printf("%d ",u);   
        }
    }
    int main() 
    { 
        // setIO("input");  
        int T;
        scanf("%d",&T);  
        while(T--) 
        {
            int a=solve_1();    
            solve_2(a);   
            for(int i=1;i<=n;++i) 
            {
                in[i]=vis[i]=del[i]=ori[i]=du[i]=0;    
            }
            clr_graph();  
            se.clear(); 
            printf("
    "); 
        }
        return 0; 
    }
    

      

  • 相关阅读:
    如何设置mysql数据库为只读
    华为S5300系列、S5700系列交换机无法修改密码问题分析
    一个form表单有两个按钮,分别提交到不同的页面
    在cmd/bat脚本中获取当前脚本文件所在目录
    以一个学生宿舍区为例,解析华为交换机AAA的配置
    mysql创建远程用户并授权
    锐捷交换机中的password与secret的区别
    机器学习基础及案例
    python所有基础
    win10找不到Hyper-V的解决方法
  • 原文地址:https://www.cnblogs.com/guangheli/p/12971448.html
Copyright © 2020-2023  润新知