洛谷P5236 圆方树模板题

狭义的圆方树   洛谷P5236 圆方树模板题

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
struct node{
    int nxt,w,to;
}e[N],E[N];
int head[N],Head[N],cnt,Cnt;
int fa[N],deep[N],top[N],son[N],siz[N],S[N],dis[N];
int n,m,q,An,Bn;
int sum[N];
int dfn[N],low[N],tot;
void add(int from,int to,int w){
    e[++cnt].nxt=head[from];
    e[cnt].w=w;
    e[cnt].to=to;
    head[from]=cnt;
}
void Add(int from,int to,int w){
    E[++Cnt].nxt=Head[from];
    E[Cnt].w=w;
    E[Cnt].to=to;
    Head[from]=Cnt;
}
void dfs1(int from,int Fa,int dep){
    fa[from]=Fa;
    deep[from]=dep;
    siz[from]=1;
    son[from]=0;
    int maxson=0;
    for(int i=Head[from];i;i=E[i].nxt){
        int to=E[i].to;
        if(to==Fa)continue;
        dis[to]=dis[from]+E[i].w;
        dfs1(to,from,dep+1);
        siz[from]+=siz[to];
        if(maxson<siz[to]){
            maxson=siz[to];
            son[from]=to;
        }
    }
}
void dfs2(int from,int topf){
    top[from]=topf;
    if(!son[from])return;
    dfs2(son[from],topf);
    for(int i=Head[from];i;i=E[i].nxt){
        int to=E[i].to;
        if(to==son[from]||to==fa[from])continue;
        dfs2(to,to);
    }
}
int lca(int x,int y){
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]])swap(x,y);
        x=fa[top[x]];
    }
    if(deep[x]>deep[y])swap(x,y);
    return x;
}
int find(int P,int x){
    int res=x;
    while(top[x]!=top[P]){
        res=top[x];
        x=fa[top[x]];
    }
    if(P==x)return res;
    else return son[P];
}
void build(int from,int to,int w){
    ++Bn;
    int now=to,res=w;
    while(now!=fa[from]){
        sum[now]=res;
        res+=S[now];
        now=fa[now];
    }
    sum[Bn]=sum[from];
    sum[from]=0;
    now=to;
    while(now!=fa[from]){
        int Bw=min(sum[now],sum[Bn]-sum[now]);
        Add(now,Bn,Bw);
        Add(Bn,now,Bw);
        now=fa[now];
    }
    return;
}
void tarjan(int from,int Fa){
    dfn[from]=low[from]=++tot;
    for(int i=head[from];i;i=e[i].nxt){
        int to=e[i].to;
        int w=e[i].w;
        if(to==Fa)continue;
        if(!dfn[to]){
            fa[to]=from;
            S[to]=w;
            tarjan(to,from);
            low[from]=min(low[from],low[to]);
        }else{
            low[from]=min(low[from],dfn[to]);
        }
        if(low[to]<=dfn[from])continue;
        Add(from,to,w);
        Add(to,from,w);
    }
    for(int i=head[from];i;i=e[i].nxt){
        int to=e[i].to;
        int w=e[i].w;
        if(fa[to]==from||dfn[to]<dfn[from])continue;
        build(from,to,w);
    }
    return;
}
int main(){
    scanf("%d%d%d",&An,&m,&q);
    for(int i=1;i<=m;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
    }
    Bn=An;
    tarjan(1,0);
    dfs1(1,0,1);
    dfs2(1,1);
    for(int i=1;i<=q;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        int L=lca(x,y);
        if(L<=An){
            int ans=dis[y]+dis[x]-2*dis[L];
            printf("%d\n",ans);
        }else{
            int X=find(L,x);
            int Y=find(L,y);
            int ans=min(abs(sum[X]-sum[Y]),sum[L]-abs(sum[X]-sum[Y]));
            ans+=dis[x]-dis[X]+dis[y]-dis[Y];
            printf("%d\n",ans);
        }
    }
}
rst

广义的圆方树 洛谷P4630 广义圆方树模板题

#include<bits/stdc++.h>
using namespace std;
const int N=500010;
struct node{
    int nxt,to;
}e[N],E[N];
int head[N],Head[N];
int cnt,Cnt,tot,num;
int dfn[N],low[N],stk[N],tp,sum[N],siz[N];
long long ans;
int n,Bn,m;
void add(int from,int to){
    e[++cnt].nxt=head[from];
    e[cnt].to=to;
    head[from]=cnt;
}
void Add(int from,int to){
    E[++Cnt].nxt=Head[from];
    E[Cnt].to=to;
    Head[from]=Cnt;
}
void tarjan(int from){
    dfn[from]=low[from]=++tot;
    stk[++tp]=from;
    num++;
    for(int i=head[from];i;i=e[i].nxt){
        int to=e[i].to;
        if(!dfn[to]){
            tarjan(to);
            low[from]=min(low[from],low[to]);
            if(low[to]==dfn[from]){
                sum[++Bn]=0;
                while(stk[tp+1]!=to){
                    Add(stk[tp],Bn);
                    Add(Bn,stk[tp]);
                    sum[Bn]++;
                    tp--;
                }
                Add(from,Bn);
                Add(Bn,from);
                sum[Bn]++;
            }
        }else {
            low[from]=min(low[from],dfn[to]);
        }
    }
}
void dfs(int from,int F){
    if(from<=n)siz[from]=1;
    for(int i=Head[from];i;i=E[i].nxt){
        int to=E[i].to;
        if(to==F)continue;
        dfs(to,from);
        ans+=(long long)2*sum[from]*siz[from]*siz[to];
        siz[from]+=siz[to];
    }
    ans+=(long long)2*sum[from]*siz[from]*(num-siz[from]);
}
int main(){
    scanf("%d%d",&n,&m);
    Bn=n;
    for(int i=1;i<=n;i++)sum[i]=-1;
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    for(int i=1;i<=n;i++){
        if(!dfn[i]){
            num=0;
            tarjan(i);
            tp--;
            dfs(i,0);
        }
    }
    printf("%lld\n",ans);
}
rst

 

posted @ 2020-02-01 16:35  passione  阅读(136)  评论(0编辑  收藏  举报