zoukankan      html  css  js  c++  java
  • BZOJ 2238: Mst DFS序+KDtree

    明明可以用二维数点来做啊,网上为什么都是树剖+线段树呢 ?  

    code: 

    #include <cstdio> 
    #include <cstring>   
    #include <algorithm>   
    #define N 100006 
    #define inf 1000000
    #define ll long long 
    #define IO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)  
    using namespace std;                     
    namespace KD {    
    
        int d; 
        struct node { 
            int ch[2],p[2],mn[2],mx[2],Min,val;     
        }t[N];             
    
        bool cmp(node a,node b) 
        { 
            return a.p[d]==b.p[d]?a.p[d^1]<b.p[d^1]:a.p[d]<b.p[d];  
        }  
    
        int isin(int x1,int y1,int x2,int y2,int x) 
        {   
            if(t[x].mn[0]>=x1&&t[x].mx[0]<=y1&&t[x].mn[1]>=x2&&t[x].mx[1]<=y2)  
                return 1; 
            return 0; 
        } 
    
        int isout(int x1,int y1,int x2,int y2,int x) 
        {   
            if(x1>t[x].mx[0]||y1<t[x].mn[0]||x2>t[x].mx[1]||y2<t[x].mn[1])  
                return 1; 
            return 0; 
        }
    
        void pushup(int x,int y) 
        {   
            for(int i=0;i<2;++i) 
            {
                t[x].mn[i]=min(t[x].mn[i],t[y].mn[i]);   
                t[x].mx[i]=max(t[x].mx[i],t[y].mx[i]);  
            }
            t[x].Min=min(t[x].Min,t[y].Min);  
        }
    
        int build(int l,int r,int o) 
        {   
            d=o; 
            int mid=(l+r)>>1;    
            nth_element(t+l,t+mid,t+1+r,cmp);          
            t[mid].mn[0]=t[mid].mx[0]=t[mid].p[0]; 
            t[mid].mn[1]=t[mid].mx[1]=t[mid].p[1];      
            t[mid].Min=t[mid].val;    
            if(mid>l)     
            {
                t[mid].ch[0]=build(l,mid-1,o^1); 
                pushup(mid,t[mid].ch[0]); 
            }
            if(r>mid)  
            {
                t[mid].ch[1]=build(mid+1,r,o^1);   
                pushup(mid,t[mid].ch[1]); 
            }
            return mid;     
        } 
    
        int query(int x1,int y1,int x2,int y2,int x) 
        { 
            if(isout(x1,y1,x2,y2,x))  return inf;  
            if(isin(x1,y1,x2,y2,x))   return t[x].Min;      
            int re=inf;                 
            if(t[x].p[0]>=x1&&t[x].p[0]<=y1&&t[x].p[1]>=x2&&t[x].p[1]<=y2) 
            {
                re=min(re,t[x].val);    
            }     
            if(t[x].ch[0])   re=min(re,query(x1,y1,x2,y2,t[x].ch[0]));   
            if(t[x].ch[1])   re=min(re,query(x1,y1,x2,y2,t[x].ch[1]));    
            return re;  
        }
    
    }; 
    namespace T {   
        int p[N];  
    
        void init(int x) 
        { 
            for(int i=1;i<=x;++i) p[i]=i; 
        }    
    
        int find(int x) 
        {
            return p[x]==x?x:p[x]=find(p[x]); 
        }    
    
        int merge(int x,int y) 
        {
            x=find(x),y=find(y); 
            if(x!=y) 
            {
                p[x]=y;           
                return 1; 
            } 
            else return 0;     
        }
    
    }; 
    
    struct Edge {
        int x,y,c,id;     
        Edge(int x=0,int y=0,int c=0,int id=0):x(x),y(y),c(c),id(id){}  
        bool operator<(Edge a) const { return c<a.c; }            
    }e[N];  
    int n,m,edges,dfn;   
    int hd[N],to[N<<1],nex[N<<1],val[N<<1],mk[N],fa[N],st[N],ed[N],go[N];   
    
    void add(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;       
        st[u]=++dfn; 
        for(int i=hd[u];i;i=nex[i]) 
        { 
            int v=to[i]; 
            if(v==ff)  continue;    
            dfs(v,u);      
        } 
        ed[u]=dfn; 
    } 
    
    int main() 
    {   
        // IO("input"); 
        int i,j;   
        scanf("%d%d",&n,&m);   
        for(i=1;i<=m;++i) 
        {
            int x,y,z; 
            scanf("%d%d%d",&x,&y,&z);             
            e[i]=Edge(x,y,z,i);     
        }
        sort(e+1,e+1+m);            
        T::init(n);         
        ll ans=0;  
        int cn=0,tot=0;   
        for(i=1;i<=m;++i) 
        {    
            if(T::merge(e[i].x,e[i].y))          
            {
                ans+=(ll)e[i].c; 
                mk[e[i].id]=1,++cn; 
                add(e[i].x,e[i].y,e[i].c); 
                add(e[i].y,e[i].x,e[i].c);      
            }  
        }                             
        if(cn==n-1) dfs(1,0);  
        for(i=1;i<=m;++i) 
        {   
            go[e[i].id]=i;                  
            if(!mk[e[i].id]) 
            {   
                int x=e[i].x; 
                int y=e[i].y;        
                if(st[x]>st[y]) swap(x,y);  
                ++tot;              
                KD::t[tot].val=e[i].c;   
                KD::t[tot].p[0]=st[x];    
                KD::t[tot].p[1]=st[y];                      
            }
        }
        int root=KD::build(1,tot,0); 
        int q; 
        scanf("%d",&q);   
        for(i=1;i<=q;++i) 
        {
            int cur;  
            scanf("%d",&cur);                        
            if(cn<n-1)   printf("Not connected
    ");  
            else 
            {     
                if(!mk[cur])   printf("%lld
    ",ans);  
                else 
                { 
                    cur=go[cur];                     
                    int x=e[cur].x; 
                    int y=e[cur].y;   
                    if(fa[y]==x)  swap(x,y);    
                    int re=inf;   
                    if(st[x]>1)  
                    { 
                        re=min(re,KD::query(1,st[x]-1,st[x],ed[x],root));     
                    } 
                    if(ed[x]<n)        
                    {       
                        re=min(re,KD::query(st[x],ed[x],ed[x]+1,n,root));                
                    }          
                    if(re==inf)  printf("Not connected
    ");  
                    else printf("%lld
    ",ans-e[cur].c+re);   
                }
            }
        }
        return 0; 
    }   
    

      

  • 相关阅读:
    day103 跨域请求 与频率访问限制.
    day 102 GIT 的使用方法.
    day 101 天
    day 100天 VUE 父子传值,单页面.
    JS 在元素后插入元素
    JS 网页加载后执行多个函数
    MySQL 一般操作语句
    PHP 通过设置表单元素name属性生成数组
    PHP SQL语气中value必须添加单引号
    PHP 单引号和双引号的区别
  • 原文地址:https://www.cnblogs.com/guangheli/p/12093064.html
Copyright © 2011-2022 走看看