HDU 5770 Treasure

来源:互联网 发布:mac系统pdf编辑软件 编辑:程序博客网 时间:2024/06/09 21:36

Description

?? has got a treasure map,the treasure map consists of N nodes,there are N-1 bidirectional roads, Each of them connects a pair of nodes,the N nodes are all connected by the N-1 bidirectional roads.?? can travel through the roads.
There are M treasures in some node. Each treasure has a value, treasures are put into boxs,each treasure corresponds to a box and each box corresponds to a key which is also in some node. Now ?? wants to plan a simple path, the path’s start point is node A,and the path’s destination is node B,?? will go from node A to node B. When ?? goes through a node(including node A and node B), he must first collects all keys, and then must open the boxes he can open in this node. The keys he got never disappear during the travel. Now ?? wants to know the maximum value he could get if he plan a best path.Can you help him?

Solution

坑走我一个早上和一个下午。。
于是我敲出了人生最长代码,打破了维修数列的记录。。

这题还是蛮牛逼的,orz现场A掉的THU大神们

我们数形结合地考虑这题
先处理出dfs序
又两点确定一条路径,那么我们可以用两个dfs序来映射一条路径
然后对于每个宝藏我们可以坐标系上的矩形来表示可以得到这个宝藏的路径
细节非常繁琐,但是不难推导,直接复制题解

假设钥匙在节点A,宝箱在节点B,C=LCA(A,B),则可以分四种情况讨论

1.CA,CB

对于这种情况,只要起点在以A为根的子树中,终点在以B为根的子树中,都可以拿到这份宝藏,而子树A中的所有节点dfs序连续,子树B同理,于是我们可以用一个矩阵表示能取得该宝藏的所有方案。

2.C=A,AB

对于这种情况,需要先求出节点D,D为路径(A,B)上最靠近A的节点,那么只要终点在子树B上,起点不在子树D上的路径,都可以拿到这份宝藏,而不在子树D上的点,可以用一个或者两个dfs序区间表示,因此可以用最多两个矩阵表示能取得该宝藏的所有方案。

3.C=B,AB

和情况2类似。

4.A=B

对于这种情况,若要求出所有经过节点A的路径,矩阵数目会是n2级别的,因此反过来思考,求出所有不包含节点A的路径,对于全部这种情况来说这样矩阵数目的级别为n。可以对答案先累加宝藏权值,然后对于所有不经过该点的矩阵减去这部分权值即可。

然后我们就得到了一坨矩形,用扫描线套个线段树即可求得最大值

其实还是不太难的
这个形数形结合结合还是很有借鉴意义的。。

Code(代码我缩过了)

#include<iostream>#include<stdio.h>#include<string.h>#include<time.h>#include<stdlib.h>#include<math.h>#include<algorithm>#include<vector>#include<string>#include<queue>#include<stack>#include<set>#include<map>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef vector<int> vec;typedef pair<int,int> pii;typedef vector<pii> vecp;#define pb push_back#define ph push#define fi first#define se secondconst int INF=(unsigned)-1>>1;const ll inf=1ll<<62;template<class T>void rd(T &a){    a=0;char c;    while(c=getchar(),!isdigit(c));    do a=a*10+(c^48);        while(c=getchar(),isdigit(c));}template<class T>void nt(T x){    if(!x)return;    nt(x/10);    putchar(48+x%10);}template<class T>void pt(T x){    if(!x)putchar('0');    else nt(x);}template<class T>void Max(T &a,T b){    if(a<b)a=b;}template<class T>void Min(T &a,T b){    if(a==-1||a>b)a=b;}const int M=1e5+5;struct Edge{int to,nxt;}G[M<<1];int head[M],tot_edge;inline void add_edge(int from,int to){    G[tot_edge]=(Edge){to,head[from]};    head[from]=tot_edge++;}int dfn[M],f[M][20],dfs_clock,dft[M],n,m,d[M],_;inline void up(int &u,int x){    for(int i=0;i<20;++i)        if(x&1<<i)u=f[u][i];}inline int lca(int u,int v){    if(d[u]<d[v])swap(u,v);    up(u,d[u]-d[v]);    if(u==v)return u;    for(int i=19;~i;--i)        if(f[u][i]^f[v][i])u=f[u][i],v=f[v][i];    return f[u][0];}inline void dfs(int v,int fa){    dfn[v]=++dfs_clock;    f[v][0]=fa,d[v]=d[fa]+1;    for(int i=head[v];~i;i=G[i].nxt){        int to=G[i].to;        if(to==fa)continue;        dfs(to,v);    }    dft[v]=dfs_clock;}inline void pret(){    for(int j=1;j<20;++j)        for(int i=1;i<=n;++i)            f[i][j]=f[f[i][j-1]][j-1];}struct Segment_Tree{    struct node{        int l,r,mx,add;    }tree[M<<2];    inline void up(int &p){        tree[p].mx=max(tree[p<<1].mx,tree[p<<1|1].mx);    }    inline void down(int &p){        if(!tree[p].add)return;        tree[p<<1].add+=tree[p].add;        tree[p<<1|1].add+=tree[p].add;        tree[p<<1].mx+=tree[p].add;        tree[p<<1|1].mx+=tree[p].add;        tree[p].add=0;    }    void build(int l=1,int r=n,int p=1){        tree[p]=(node){l,r,0,0};        if(l==r)return;        int mid=l+r>>1;        build(l,mid,p<<1);        build(mid+1,r,p<<1|1);    }    void update(int l,int r,const int x,const int flag,int p){        if(tree[p].l==l&&tree[p].r==r){            tree[p].add+=x*flag;            tree[p].mx+=x*flag;            return;        }        down(p);        int mid=tree[p].l+tree[p].r>>1;        if(r<=mid)update(l,r,x,flag,p<<1);        else if(l>mid)update(l,r,x,flag,p<<1|1);        else update(l,mid,x,flag,p<<1),update(mid+1,r,x,flag,p<<1|1);        up(p);    }    inline int query(){        return tree[1].mx;    }}sgt;struct Matrix{int l,r,v;};vector<Matrix>MatI[M],MatT[M];int txt;inline void gao(){    cin>>n>>m;    memset(head,-1,sizeof(head));    tot_edge=dfs_clock=0;    for(int i=1;i<=n;++i)        MatI[i].clear(),MatT[i].clear();    for(int i=1,a,b;i<n;++i){        rd(a),rd(b);        add_edge(a,b),add_edge(b,a);    }    dfs(1,1);    pret(),sgt.build();    int res=0,ans=-INF;    for(int i=1,a,b,v;i<=m;++i){        rd(a),rd(b),scanf("%d",&v);        int w=lca(a,b);        if(a==b){            res+=v,v=-v;            int l=dfn[a],r=dft[a];            if(l-1>=1){                MatI[1].pb((Matrix){1,l-1,v});                MatT[l-1].pb((Matrix){1,l-1,v});            }            if(r+1<=n){                MatI[r+1].pb((Matrix){r+1,n,v});                MatT[n].pb((Matrix){r+1,n,v});            }            if(l-1>=1&&r+1<=n){                MatI[1].pb((Matrix){r+1,n,v});                MatT[l-1].pb((Matrix){r+1,n,v});                MatI[r+1].pb((Matrix){1,l-1,v});                MatT[n].pb((Matrix){1,l-1,v});            }            for(int i=head[a];~i;i=G[i].nxt){                int to=G[i].to;                if(to==f[a][0])continue;                MatI[dfn[to]].pb((Matrix){dfn[to],dft[to],v});                MatT[dft[to]].pb((Matrix){dfn[to],dft[to],v});            }            continue;        }        if(a==w){            int k=b;up(k,d[b]-d[w]-1);            if(dfn[a]>1){                MatI[1].pb((Matrix){dfn[b],dft[b],v});                MatT[dfn[a]-1].pb((Matrix){dfn[b],dft[b],v});            }            if(dft[a]<n){                MatI[dft[a]+1].pb((Matrix){dfn[b],dft[b],v});                MatT[n].pb((Matrix){dfn[b],dft[b],v});            }            if(dfn[a]<dfn[k]){                MatI[dfn[a]].pb((Matrix){dfn[b],dft[b],v});                MatT[dfn[k]-1].pb((Matrix){dfn[b],dft[b],v});            }            if(dft[a]>dft[k]){                MatI[dft[k]+1].pb((Matrix){dfn[b],dft[b],v});                MatT[dft[a]].pb((Matrix){dfn[b],dft[b],v});            }            continue;        }        if(b==w){            int k=a;up(k,d[a]-d[w]-1);            int l=dfn[a],r=dft[a];            if(dfn[b]>1){                MatI[l].pb((Matrix){1,dfn[b]-1,v});                MatT[r].pb((Matrix){1,dfn[b]-1,v});            }            if(dft[b]<n){                MatI[l].pb((Matrix){dft[b]+1,n,v});                MatT[r].pb((Matrix){dft[b]+1,n,v});            }            MatI[l].pb((Matrix){dfn[b],dfn[k]-1,v});            MatT[r].pb((Matrix){dfn[b],dfn[k]-1,v});            if(dft[k]<dft[b]){                MatI[l].pb((Matrix){dft[k]+1,dft[b],v});                MatT[r].pb((Matrix){dft[k]+1,dft[b],v});            }            continue;        }        int l=dfn[a],r=dft[a];        MatI[l].pb((Matrix){dfn[b],dft[b],v});        MatT[r].pb((Matrix){dfn[b],dft[b],v});    }    for(int i=1;i<=n;++i){        for(int j=0;j<MatI[i].size();++j){            Matrix v=MatI[i][j];            sgt.update(v.l,v.r,v.v,1,1);        }        Max(ans,res+sgt.query());        for(int j=0;j<MatT[i].size();++j){            Matrix v=MatT[i][j];            sgt.update(v.l,v.r,v.v,-1,1);        }    }    printf("Case #%d: ",++txt);    cout<<ans<<endl;}int main(){    for(cin>>_;_--;)gao();    return 0;}
0 0
原创粉丝点击