• 图论复习


    就是一道树剖的裸题 实话说树剖细节挺多的

    我打这个代码的时候遗漏的细节

    1;有重儿子才先进行重儿子遍历 比如叶节点没有重儿子(默认为0) 是不能遍历的 不然会死循环

    2;初始赋值的时候 是对1-n这有序的线段树进行赋值 所以有个rk[] 这个非常易错!!!! 出题人比较狡诈 样例能过

    因为每个节点有个初始id 给出val的时候是有序的 让我们误以为直接赋值线段树就好 但是我们赋值是新的dfs序

    #include<bits/stdc++.h>
    using namespace std;
    #define lowbit(x) x&(-x)
    #define ll long long
    const int maxn=1e5+5;
    vector<int>Q[maxn];
    int cnt,n,m;
    struct node{
    	int l,r,maxx,sum;
    }tr[maxn<<2];
    int val[maxn],dfn[maxn],fa[maxn],top[maxn],sz[maxn],son[maxn],dp[maxn],rk[maxn]; 
    void up(int);
    void bd(int,int,int);
    int qmax(int,int,int,int,int);
    int qsum(int,int,int,int,int);
    void upd(int,int,int,int,int);
    int Qmax(int,int);
    int Qsum(int,int);
    void Upd(int,int);
    void dfs1(int,int);
    void dfs2(int,int);
    int main(){
    	cin>>n;
    	for(int i=1;i<n;i++){
    		int a,b;cin>>a>>b;
    		Q[a].push_back(b);
    		Q[b].push_back(a);
    	}
    	for(int i=1;i<=n;i++)cin>>val[i];
    	fa[1]=1;
    	dfs1(1,1);
    	dfs2(1,1);
    	bd(1,1,n);
    	cin>>m;
    	while(m--){
    		string s;int a,b;
    		cin>>s>>a>>b;
    		if(s=="QMAX")cout<<Qmax(a,b)<<endl;
    		else if(s=="QSUM")cout<<Qsum(a,b)<<endl;
    		else upd(1,1,n,dfn[a],b);
    	}
         return 0;
    }
    void dfs1(int u,int f){
    	sz[u]=1;
    	for(int i=0;i<Q[u].size();i++){
    		int to=Q[u][i];
    		if(to==f)continue;
    		dp[to]=dp[u]+1;fa[to]=u;
    		dfs1(to,u);
    		sz[u]+=sz[to];
    		if(sz[son[u]]<sz[to])son[u]=to;
    	}
    }
    void dfs2(int u,int tp){
    	top[u]=tp;dfn[u]=++cnt;rk[cnt]=u;
    	if(son[u])    //////
    	dfs2(son[u],tp);
    	for(int i=0;i<Q[u].size();i++){
    		int to=Q[u][i];
    		if(to==son[u]||to==fa[u])continue;
    		dfs2(to,to);
    	}
    }
    void up(int k){
    	tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
    	tr[k].maxx=max(tr[k<<1].maxx,tr[k<<1|1].maxx);
    	return;
    }
    void bd(int k,int l,int r){
    	if(r<l)return;
    	if(l==r){
    		tr[k].l=l,tr[k].r=r;
    		tr[k].sum=tr[k].maxx=val[rk[l]];/////
    		return;
    	}
    	int mid=l+r>>1;
    	bd(k<<1,l,mid);
    	bd(k<<1|1,mid+1,r);
    	up(k);
    }
    int qmax(int k,int l,int r,int L,int R){
    	if(L<=l&&r<=R)return tr[k].maxx;
    	int mid=l+r>>1;
    	int res=-1e9;
    	if(mid>=L)res=max(res,qmax(k<<1,l,mid,L,R));
    	if(mid<R)res=max(res,qmax(k<<1|1,mid+1,r,L,R));
    	up(k);
    	return res;
    }
    int qsum(int k,int l,int r,int L,int R){
    	if(L<=l&&r<=R)return tr[k].sum;
    	int mid=l+r>>1;
    	int res=0;
    	if(mid>=L)res+=qsum(k<<1,l,mid,L,R);
    	if(mid<R)res+=qsum(k<<1|1,mid+1,r,L,R);
    	up(k);
    	return res;
    }
    void upd(int k,int l,int r,int pos,int w){
    	if(l==r){
    		tr[k].maxx=tr[k].sum=w;
    		return;
    	}
    	int mid=l+r>>1;
    	if(pos<=mid)upd(k<<1,l,mid,pos,w);
    	else upd(k<<1|1,mid+1,r,pos,w);
    	up(k);
    }
    int Qsum(int u,int v){
    	int res=0;
    	while(top[u]!=top[v]){
    		if(dp[top[u]]<dp[top[v]])swap(u,v);
    		res+=qsum(1,1,n,dfn[top[u]],dfn[u]);
    		u=fa[top[u]];
    	}
    	if(dp[u]<dp[v])swap(u,v);
    	res+=qsum(1,1,n,dfn[v],dfn[u]);
    	return res;
    }
    int Qmax(int u,int v){
    	int res=-1e9;
    	while(top[u]!=top[v]){
    		if(dp[top[u]]<dp[top[v]])swap(u,v);
    		res=max(res,qmax(1,1,n,dfn[top[u]],dfn[u]));
    		u=fa[top[u]];
    	}
    	if(dp[u]<dp[v])swap(u,v);
    	res=max(res,qmax(1,1,n,dfn[v],dfn[u]));
    	return res;
    }
    

    RMQ上维护最大和次大还是要注意一下的

    点击查看代码
    #include<bits/stdc++.h>
    #define N 400010
    #define M 900010
    #define INF 2147483647000000
    #define ll long long
    
    using namespace std;
    
    struct edge{
        ll u,v,d;
        ll next;
    }G[N<<1];
    ll tot=0;
    ll head[N];
    inline void addedge(ll u,ll v,ll d)
    {
        G[++tot].u=u,G[tot].v=v,G[tot].d=d,G[tot].next=head[u],head[u]=tot;
        G[++tot].u=v,G[tot].v=u,G[tot].d=d,G[tot].next=head[v],head[v]=tot;
    }
    
    ll bz[N][19];
    ll maxi[N][19];
    ll mini[N][19];
    ll deep[N];
    inline void dfs(ll u,ll fa)
    {
        bz[u][0]=fa;
        for(ll i=head[u];i;i=G[i].next)
        {
            ll v=G[i].v;
            if(v==fa)continue;
            deep[v]=deep[u]+1ll;
            maxi[v][0]=G[i].d;
            mini[v][0]=-INF;
            dfs(v,u);
        }
    }
    
    ll n;
    inline void cal()
    {
        for(ll i=1;i<=18;++i)
            for(ll j=1;j<=n;++j)
            {
                bz[j][i]=bz[bz[j][i-1]][i-1];
                maxi[j][i]=max(maxi[j][i-1],maxi[bz[j][i-1]][i-1]);
                mini[j][i]=max(mini[j][i-1],mini[bz[j][i-1]][i-1]);
                if(maxi[j][i-1]>maxi[bz[j][i-1]][i-1])mini[j][i]=max(mini[j][i],maxi[bz[j][i-1]][i-1]);
                else if(maxi[j][i-1]<maxi[bz[j][i-1]][i-1])mini[j][i]=max(mini[j][i],maxi[j][i-1]);
            }
    }
    
    inline ll LCA(ll x,ll y)
    {
        if(deep[x]<deep[y])swap(x,y);
        for(ll i=18;i>=0;--i)
            if(deep[bz[x][i]]>=deep[y])
                x=bz[x][i];
        if(x==y)return x;
        for(ll i=18;i>=0;--i)
            if(bz[x][i]^bz[y][i])
                x=bz[x][i],y=bz[y][i];
        return bz[x][0];
    }
    
    inline ll qmax(ll u,ll v,ll maxx)
    {
        ll Ans=-INF;
        for(ll i=18;i>=0;--i)
        {
            if(deep[bz[u][i]]>=deep[v])
            {
                if(maxx!=maxi[u][i])Ans=max(Ans,maxi[u][i]);
                else Ans=max(Ans,mini[u][i]);
                u=bz[u][i];
            }
        }
        return Ans;
    }
    
    inline void read(ll &x)
    {
        x=0;
        char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+(ch^48),ch=getchar();
    }
    
    ll m;
    
    edge A[M<<1];
    
    inline bool cmp(edge x,edge y)
    {
        return x.d<y.d;
    }
    
    ll Father[N];
    inline ll Get_Father(ll x)
    {
        return (x==Father[x]) ? x : Father[x]=Get_Father(Father[x]);
    }
    
    bool B[M<<1];
    
    int main()
    {
        read(n),read(m);
        for(ll i=1;i<=m;++i)
        {
            read(A[i].u),read(A[i].v),read(A[i].d);
        }
    
        sort(A+1,A+m+1,cmp);
    
        for(ll i=1;i<=n;++i)
            Father[i]=i;
    
        ll Cnt=0ll;
        for(ll i=1;i<=m;++i)
        {
            ll Father_u=Get_Father(A[i].u);
            ll Father_v=Get_Father(A[i].v);
            if(Father_u!=Father_v)
            {
                Cnt+=A[i].d;
                Father[Father_u]=Father_v;
                addedge(A[i].u,A[i].v,A[i].d);
                B[i]=true;
            }
        }
    
        mini[1][0]=-INF;
        deep[1]=1;
        dfs(1,-1);
        cal();
    
        ll Ans=INF;
    
        for(ll i=1;i<=m;++i)
        {
            if(!B[i])
            {
                ll u=A[i].u;
                ll v=A[i].v;
                ll d=A[i].d;
                ll lca=LCA(u,v);
                ll maxu=qmax(u,lca,d);
                ll maxv=qmax(v,lca,d);
                Ans=min(Ans,Cnt-max(maxu,maxv)+d);
            }
        }
    
        printf("%lld",Ans);
    
        return 0;
    }
    

    针对瓶颈生成树 根据其充分性可以直接用最小生成树来解决

  • 相关阅读:
    解决跨域问题
    封装树形结构数据
    使用脚手架搭建vue项目
    Vue入门之HelloWorld
    element-ui 格式化树形数组在table组件中展示(单元格合并)
    js导出excel,时间格式问题
    webpack代理设置
    null和undefined的区别?
    js Number和parseInt 的区别
    js数据类型
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/16194021.html
Copyright © 2020-2023  润新知