[BZOJ2238]Mst:树链剖分+线段树

分析:

待会补。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}

const int MAXN=50005;
const int MAXM=100005;
int n,m,ecnt,head[MAXN],fa[MAXN],tnum[MAXM],pos[MAXM];
int dep[MAXN],siz[MAXN],pc[MAXN],top[MAXN],id[MAXN],tot;
int minn[MAXN<<2],mdf[MAXN<<2],loc,ql,qr,kk;
bool vis[MAXM],tvis[MAXM];
struct Edge{
    int to,nxt,w,id;
}e[MAXN<<1];
struct PosEdge{
    int u,v,w,id;
    friend bool operator < (PosEdge x,PosEdge y){
        return x.w<y.w;
    }
}ee[MAXM];

inline void add_edge(int bg,int ed,int val,int idd){
    ecnt++;
    e[ecnt].to=ed;
    e[ecnt].nxt=head[bg];
    e[ecnt].w=val;
    e[ecnt].id=idd;
    head[bg]=ecnt;
}

int getf(int x){
    return fa[x]==x?x:fa[x]=getf(fa[x]);
}

inline bool mer(int x,int y){
    int xx=getf(x),yy=getf(y);
    if(xx!=yy){
        fa[yy]=xx;
        return 1;
    }
    return 0;
}

void dfs1(int x,int pre,int depth){
    fa[x]=pre;
    dep[x]=depth;
    siz[x]=1;
    int maxsiz=-1;
    for(int i=head[x];i;i=e[i].nxt){
        int ver=e[i].to;
        if(ver==pre) continue;
        pos[e[i].id]=ver;
        dfs1(ver,x,depth+1);
        siz[x]+=siz[ver];
        if(maxsiz<siz[ver])
            maxsiz=siz[ver],pc[x]=ver;
    }
}

void dfs2(int x,int topf){
    top[x]=topf;
    id[x]=++tot;
    if(!pc[x]) return;
    dfs2(pc[x],topf);
    for(int i=head[x];i;i=e[i].nxt){
        int ver=e[i].to;
        if(ver==fa[x]||ver==pc[x]) continue;
        dfs2(ver,ver);
    }
}

#define mid ((l+r)>>1)
#define lc (o<<1)
#define rc ((o<<1)|1)
inline void pushdown(int o){
    if(mdf[o]>=1e9) return;
    minn[lc]=minn[rc]=mdf[lc]=mdf[rc]=mdf[o];
    mdf[o]=1e9;
}

void rset(int o,int l,int r){
    if(ql<=l&&r<=qr){
        minn[o]=kk;
        mdf[o]=kk;
        return;
    }
    pushdown(o);
    if(mid>=ql) rset(lc,l,mid);
    if(mid<qr) rset(rc,mid+1,r);
    minn[o]=std::min(minn[lc],minn[rc]);
}

int sinq(int o,int l,int r){
    if(l==r&&l==loc) return minn[o];
    pushdown(o);
    if(loc<=mid) return sinq(lc,l,mid);
    else return sinq(rc,mid+1,r);
}
#undef mid
#undef lc
#undef rc

void pathset(int x,int y,int val){
    kk=val;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
        ql=id[top[x]],qr=id[x];
        rset(1,1,n);
        x=fa[top[x]];
    }
    if(x==y) return;
    if(dep[x]>dep[y]) std::swap(x,y);
    ql=id[x]+1,qr=id[y];
    rset(1,1,n);
}

int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=m;i++){
        ee[i].u=read(),ee[i].v=read(),ee[i].w=read();
        ee[i].id=i,tnum[i]=ee[i].w;
    }
    std::sort(ee+1,ee+m+1);
    int ans=0,cnt=0;bool flag=0;
    for(int i=1;i<=m;i++)
        if(mer(ee[i].u,ee[i].v)){
            cnt++;
            ans+=ee[i].w;
            vis[i]=1;tvis[ee[i].id]=1;
            add_edge(ee[i].u,ee[i].v,ee[i].w,ee[i].id);
            add_edge(ee[i].v,ee[i].u,ee[i].w,ee[i].id);
        }
    if(cnt<n-1) flag=1;
    memset(fa,0,sizeof fa);
    dfs1(1,0,1);
    dfs2(1,1);
    memset(minn,0x3f,sizeof minn);
    memset(mdf,0x3f,sizeof mdf);
    for(int i=m;i;i--){
        if(vis[i]) continue;
        pathset(ee[i].u,ee[i].v,ee[i].w);
    }
    int T=read();
    while(T--){
        int x=read(),y=pos[x],z=id[y];
        if(flag){
            printf("Not connected\n");
            continue;
        }
        if(!tvis[x]){
            printf("%d\n",ans);
            continue;
        }
        loc=z;
        int ret=sinq(1,1,n);
        if(ret<1e9) printf("%d\n",ans-tnum[x]+ret);
        else printf("Not connected\n");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9725052.html