BZOJ 3319: 黑白树 树+并查集+未调完+神题

Code:

#include<bits/stdc++.h>
#define maxn 1000003 
using namespace std;
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {int x=0,f=1; char c=nc(); while(c<48) {if(c=='-') f=-1; c=nc();} while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x*f;}
void setIO(string s)
{
    string in=s+".in", out=s+".out"; 
    freopen(in.c_str(),"r",stdin); 
    freopen(out.c_str(),"w",stdout); 
} 
int n,Q,edges; 
int hd[maxn],to[maxn<<1],nex[maxn<<1],val[maxn<<1],fa[maxn],dep[maxn],p[maxn],mark[maxn],tag[maxn]; 
int pd[maxn], answer[maxn]; 
void Init()
{
    for(int i=0;i<maxn;++i) p[i]=i; 
}         
int find(int x)
{
    return p[x]==x?x:p[x]=find(p[x]);   
}
void addedge(int u,int v,int c)
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;  
}
void dfs(int u,int ff)
{
    fa[u]=ff; 
    for(int i=hd[u];i;i=nex[i])
    {
        int v=to[i]; 
        if(v==ff) continue;  
        dep[v]=dep[u]+1; 
        mark[v]=val[i];             
        dfs(v,u); 
    }
}
struct OPT
{
    int o,u,v; 
}opt[maxn];   
void _2(int u,int v,int cur)
{
    u=find(u),v=find(v); 
    while(u!=v)
    {
        // v is deeper than u 
        if(dep[u] > dep[v]) swap(u,v);  
        if(!pd[v]) p[v]=find(fa[v]), pd[v]=cur; 
       //  printf("%d %d\n",dep[u],dep[v]); 
        v = p[v]; 
    }
}
//set u -> v to white 
void solve(int u,int v,int cur)
{
    u=find(u),v=find(v); 
    while(u!=v)     
    {
        if(dep[u] > dep[v]) swap(u,v); 
        if(pd[v]==cur) p[v]=find(fa[v]);                     
        v = p[fa[v]];                  // 暴力跳QAQ......    
        //v=p[v]; 
    }
}             
int main()
{
  //   setIO("input"); 
   // scanf("%d%d",&n,&Q);
    n=rd(),Q=rd(); 
    for(int i=1;i<n;++i)
    {
        int u,v; 
        u=rd(),v=rd(); 
        //scanf("%d%d",&u,&v); 
        addedge(u,v,i);
        addedge(v,u,i); 
    }
    dep[1]=1; 
    dfs(1,0);          
    for(int i=1;i<=Q;++i)
    {
        opt[i].o=rd(); 
        //scanf("%d",&opt[i].o); 
        if(opt[i].o==1)  opt[i].u=rd(); 
           // scanf("%d",&opt[i].u); 
        else opt[i].u=rd(), opt[i].v=rd(); 
           // scanf("%d%d",&opt[i].u,&opt[i].v); 
    }
    // 处理黑点情况. 
    Init();             
    for(int i=1;i<=Q;++i)
    { 
        if(opt[i].o==2) _2(opt[i].u,opt[i].v,i); 
    }
    Init(); 
    for(int i=2;i<=n;++i) 
    {
        if(!pd[i])               //到最后也未被染成黑色 直接用并查集连上   
        {    
            int u = fa[i], v = i; 
            int x = find(u); 
            p[v] = x; 
        }
    }         
    int tot = 0; 
    for(int i=Q;i>=1;--i)
    {
        if(opt[i].o==2)
        {
            //debug(); 
            solve(opt[i].u, opt[i].v, i);    
            // debug(); 
        }
        else 
        {
            int x = find(opt[i].u);   
            answer[++tot]=mark[x];           
        }
    }
    for(int i=tot;i>=1;--i) printf("%d\n",answer[i]); 
    return 0; 
}

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/11015912.html
今日推荐