F. Berland Beauty(树链剖分)

http://codeforces.com/problemset/problem/1296/F

题意:

一棵树,边权,给出很多条路径的信息(路径上的最小值),求一个合法的树

解析:

最小值为X相当于全部大于等于X。所以树链剖分,区间取最大值即可。

判断不存在:

按照每条边当前权值重新建树,求区间最小值。如果和之前的区间最小值不一样就是-1。(例如[1,4]=2,[1,2]=3,[2,4]=5,显然不成立)

代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<limits.h>
using namespace std;
#define rep(i,a,b) for(register int i=a;i<=b;i++)
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+r>>1)
#define root int rt,int l,int r
#define lson ls,l,mid
#define rson rs,mid+1,r


const int maxn=1e4+4;
int n;
int v[maxn];//点权
int head[maxn],nex[maxn<<1],val[maxn<<1],to[maxn<<1],now;
int fa[maxn],dep[maxn],siz[maxn],son[maxn];

int pointid(int edge){
	int p1=to[(edge<<1)-1];// 链式前向星存图
    int p2=to[edge<<1];
    int p=p1;
    if(dep[p2]>dep[p1])p=p2;
    return p;
}

inline void add(int a,int b,int v){
    nex[++now]=head[a];head[a]=now;to[now]=b;val[now]=v;
}

//************************************************
int w[maxn];//线段树基础数组
int tr[maxn<<2];//线段树
int lz[maxn<<2];
void build(int rt,int l,int r){
    if(l==r){tr[rt]=w[l];lz[rt]=0;return;}
    build(lson);
    build(rson);
    tr[rt]=max(tr[ls],tr[rs]);
}
void pushdown(int rt){
    if(lz[rt]){
        tr[ls]=max(tr[ls],lz[rt]);
        tr[rs]=max(tr[rs],lz[rt]);
        lz[ls]=max(lz[ls],lz[rt]);
        lz[rs]=max(lz[rs],lz[rt]);
        lz[rt]=0;
    }
}
void update(root,int L,int R,int val){
    if(l>=L&&r<=R){
        tr[rt]=max(tr[rt],val);
        lz[rt]=max(lz[rt],val);
        return ;
    }
    pushdown(rt);
    if(L<=mid)update(lson,L,R,val);
    if(R>mid)update(rson,L,R,val);
    tr[rt]=max(tr[ls],tr[rs]);
}
int query(root,int L,int R){
    if(l>=L&&r<=R){
        return tr[rt];
    }
    pushdown(rt);
    int ans=-2e9;
    if(L<=mid)ans=max(ans,query(lson,L,R));
    if(R>mid)ans=max(ans,query(rson,L,R));
    return ans;
}
//************************************************

// 跑出树的信息
void dfs_init(int p,int f,int deep){
    fa[p]=f;
    dep[p]=deep;
    siz[p]=1;
    son[p]=0;
    int maxx=-1;
    for(register int i=head[p];i;i=nex[i]){
        int uv=to[i];
        if(uv==f)continue;
        v[uv]=val[i];//边权转点权
        dfs_init(uv,p,deep+1);
        siz[p]+=siz[uv];
        if(siz[uv]>maxx){
            maxx=siz[uv];
            son[p]=uv;
        }
    }
}

// 跑出对应dfs序
int top[maxn],id[maxn];
int cnt;
void dfs(int p,int rt){
    top[p]=rt;
    id[p]=++cnt;
    w[cnt]=v[p];
    if(!son[p])return;
    // 先跑重儿子
    dfs(son[p],rt);
    for(register int i=head[p];i;i=nex[i]){
        int uv=to[i];
        if(uv==fa[p]||uv==son[p])continue;
        dfs(uv,uv); // 不是重儿子开新链
    }
}

//树操作转线段树操作
void Update(int s,int t,int val){
    while(top[s]!=top[t]){
        if(dep[top[s]]>dep[top[t]])swap(s,t);
        update(1,1,n,id[top[t]],id[t],val);
        t=fa[top[t]];
    }
    if(s==t)return ;
    if(dep[s]>dep[t])swap(s,t);
    update(1,1,n,id[s]+1,id[t],val);
}
int Query(int s,int t){
    int ans=-2e9;
    if(s==t)return ans;
    while(top[s]!=top[t]){
        if(dep[top[s]]>dep[top[t]])swap(s,t);
        ans=max(ans,query(1,1,n,id[top[t]],id[t]));
        t=fa[top[t]];
    }
    if(s==t)return ans;
    if(dep[s]>dep[t])swap(s,t);
    ans=max(ans,query(1,1,n,id[s]+1,id[t]));
    return ans;
}

void init(){
    memset(head,0,sizeof(head));
    now=cnt=0;
    memset(lz,0,sizeof lz);
}
int A[maxn],B[maxn];

void Build_Min(root){
    if(l==r){
        return;
    }
    pushdown(rt);
    Build_Min(lson);
    Build_Min(rson);
    tr[rt]=min(tr[ls],tr[rs]);
}
int query_Min(root,int L,int R){
    if(l>=L&&r<=R){
        return tr[rt];
    }
    int ans=2e9;
    if(L<=mid)ans=query_Min(lson,L,R);
    if(R>mid)ans=min(ans,query_Min(rson,L,R));
    return ans;
}
int Query_Min(int s,int t){
    int ans=2e9;
    if(s==t)return ans;
    while(top[s]!=top[t]){
        if(dep[top[s]]>dep[top[t]])swap(s,t);
        ans=min(ans,query_Min(1,1,n,id[top[t]],id[t]));
        t=fa[top[t]];
    }
    if(s==t)return ans;
    if(dep[s]>dep[t])swap(s,t);
    ans=min(ans,query_Min(1,1,n,id[s]+1,id[t]));
    return ans;
}

struct node{
    int a,b,v;
}Q[maxn];
int Ans[maxn];
int main(){
        scanf("%d",&n);
        rep(i,1,n-1){
            scanf("%d%d",A+i,B+i);
            add(A[i],B[i],0);
            add(B[i],A[i],0);
        }
        int rt=1;
        v[rt]=0;
        dfs_init(rt,-1,1);
        dfs(rt,rt);
        build(1,1,n);

        int q;scanf("%d",&q);
        rep(i,1,q){
            int a,b,v;scanf("%d%d%d",&a,&b,&v);
            Update(a,b,v);
            Q[i].a=a;
            Q[i].b=b;
            Q[i].v=v;
        }

        rep(i,1,n-1){
            Ans[i]=Query(A[i],B[i]);
        }

        Build_Min(1,1,n);
        rep(i,1,q){
            int res=Query_Min(Q[i].a,Q[i].b);
            if(Q[i].v!=res)return 0*printf("-1\n");
        }
        rep(i,1,n-1)printf("%d%c",max(1,Ans[i])," \n"[i==n-1]);
}

发布了773 篇原创文章 · 获赞 345 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/104361476