zoukankan      html  css  js  c++  java
  • 【JZOJ5248】花花的聚会

    Description

    Pic

    注意测试数据中道路是

    的单向道路,与题面恰好相反。

    Input

    Output

    Sample Input

    7 7
    1 3
    1 2
    6 7
    3 6
    3 5
    3 4
    7 2 3
    7 1 1
    2 3 5
    3 6 2
    4 2 4
    5 3 10
    6 1 20
    3
    5
    6
    7

    Sample Output

    Pic

    题解:

      这个题目,首先dp十分显然,设dp[i]表示强制在i这个节点购买的走到1号节点的最小话花费转移起来就可以了.

      但显然我们要求可以用这个票到达的祖先节点中dp[x]的最小值,考虑,将票按起点的dfn排序,每次用票来更新dp值,每次更新就在线段树里修改就可以了,线段树维护区间极小值.

    代码:

      

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #include <vector>
    #define MAXN 100010
    #define ll long long
    using namespace std;
    int n,m,q;
    int fa[MAXN],dep[MAXN],dfn[MAXN],sz[MAXN],top[MAXN],son[MAXN],id[MAXN];
    ll dp[MAXN];
    struct edge{
        int first;
        int next;
        int to;
    }a[MAXN*2];
    struct piao{
        int x,ti,co;
        void read(){
            scanf("%d%d%d",&x,&ti,&co);
        }
    }g[MAXN];
    struct tree{
        int l,r;ll minn;
    }tr[MAXN*4];
    int num=0;
    
    void addedge(int from,int to){
        a[++num].to=to;
        a[num].next=a[from].first;
        a[from].first=num;
    }
    
    void dfs1(int now,int f){
        fa[now]=f,sz[now]=1,dep[now]=dep[f]+1;
        for(int i=a[now].first;i;i=a[i].next){
            int to=a[i].to;
            if(to==f) continue;
            dfs1(to,now);
            sz[now]+=sz[to];
            if(sz[son[now]]<sz[to]) son[now]=to;
        }
    }
    
    void dfs2(int now,int tp){
        top[now]=tp;
        dfn[now]=++num;id[dfn[now]]=now;
        if(son[now]) dfs2(son[now],tp);
        for(int i=a[now].first;i;i=a[i].next){
            int to=a[i].to;
            if(to==fa[now]||to==son[now]) continue;
            dfs2(to,to);
        }
    }
    
    void pushup(int xv){
        tr[xv].minn=min(tr[xv*2].minn,tr[xv*2+1].minn);
    }
    
    void build(int xv,int l,int r){
        if(l==r){
            tr[xv].l=l,tr[xv].r=r;
            tr[xv].minn=1ll<<60;
            return;
        }
        tr[xv].l=l,tr[xv].r=r;int mid=(l+r)>>1;
        build(xv*2,l,mid),build(xv*2+1,mid+1,r);
        pushup(xv);
    }
    
    bool cmp(piao x,piao y){
        return dfn[x.x]<dfn[y.x];
    }
    
    void insert(int xv,int ps,int x){
        int l=tr[xv].l,r=tr[xv].r,mid=(l+r)>>1;
        if(l==r){
            tr[xv].minn=x;return;
        }
        if(ps<=mid) insert(xv*2,ps,x);else insert(xv*2+1,ps,x);
        pushup(xv);
    }
    
    ll query(int xv,int l,int r){
        int L=tr[xv].l,R=tr[xv].r,mid=(L+R)/2;
        if(l==L&&r==R) return tr[xv].minn;
        if(r<=mid) return query(xv*2,l,r);
        else if(l>mid) return query(xv*2+1,l,r);
        else return min(query(xv*2,l,mid),query(xv*2+1,mid+1,r));
    }
    
    ll getminn(int x,int ti){
        ll now=x,ret=dp[MAXN-2];
        while(dep[x]-dep[top[now]]<=ti&&top[now]&&now!=0){
            ret=min(ret,query(1,dfn[top[now]],dfn[now]));
            now=fa[top[now]];
        }
        if(now==0||dep[x]-dep[now]>ti) return ret;
        int l=dfn[top[now]],r=dfn[now],mid=(l+r)>>1,ans=r;
        while(l<=r){
            int mid=(l+r)/2;
            if(dep[x]-dep[id[mid]]<=ti) ans=mid,r=mid-1;
            else l=mid+1;
        }
        ret=min(ret,query(1,ans,dfn[now]));
        return ret;
    }
    
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<n;i++){
            int x,y;scanf("%d%d",&x,&y);
            addedge(y,x);
            addedge(x,y);
        }
        dfs1(1,0);num=0;
        dfs2(1,1);
        build(1,1,n);
        for(int i=1;i<=m;i++) g[i].read();
        sort(g+1,g+m+1,cmp);
        memset(dp,37,sizeof(dp));dp[1]=0;
        insert(1,1,0);
        for(int i=1;i<=m;i++){
            int co=g[i].co,ti=g[i].ti,x=g[i].x;
            if(x==1) continue;
            ll xx=getminn(x,ti);
            ll ret=getminn(x,ti)+co;
            dp[x]=min(dp[x],ret);
            insert(1,dfn[x],dp[x]);
        }
        cin>>q;
        while(q--){
            int x;scanf("%d",&x);
            printf("%lld
    ",dp[x]);
        }
        return 0;
    }
  • 相关阅读:
    2017 ACM-ICPC西安网赛B-Coin
    Codeforces389D(SummerTrainingDay01-J)
    Codeforces672D(SummerTrainingDay01-I)
    VS2017.滚动条选项
    VS.自动调试
    ffmpeg.mp4.格式资料
    vs2017.unresolved external symbol __imp__fprintf&__imp____iob_func
    vs2017."const char *"的实参与"char *"的形参不兼容_goto跳过类型声明
    vue项目开发时怎么解决跨域
    vue奇怪的知识点又增加了
  • 原文地址:https://www.cnblogs.com/renjianshige/p/9657331.html
Copyright © 2011-2022 走看看