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("\n");      
    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("\n"); 
    }
    return 0; 
}

  

posted @ 2020-05-27 11:20  EM-LGH  阅读(182)  评论(0编辑  收藏  举报