HDU 5815 Golden Week

16 篇文章 0 订阅
11 篇文章 0 订阅

Description

The ACM kingdom has N cities, numbered from 1 to N. The capital is numbered 1. There are N – 1 roads each connecting two cities in the kingdom such that there exactly one path between any pair of cities.

Now the Golden Week Vocation is coming. M travelers living in the capital are going to travel to other cities. Every traveler will start from the capital, and the ith traveler has chosen city Ci as his destination. As a manager of the travel agencies, Mr. Chopsticks decides to assign prices to the roads in the kingdom during the vocation. After some investigation, Mr. Chopsticks has found that every traveler has a budget for his trip, and if the total price of the roads in the path from the capital to his destination city is larger than his budget, he will give up his trip; otherwise he will pay for it to the travel agencies. Mr. Chopsticks wants to assign prices to roads so as to maximize the agencies’ revenue. Could you help him? Each road should be assigned a price between 0 and 1000,000,000 inclusive.

Solution

赶快截个图,待会就没了。。
这里写图片描述
截至目前(2016 08 09 22:00)的唯一AC

这题比赛的时候敲的尼玛就是正解。。然而因为懒地敲预处理弃坑了自扇2000巴掌
晚上调了2个h发现自己一个n打成m。。

这题就是一个简单的树形dp
f[i][j]表示第i个点分到j的cost可以得到的最大获益,因为cost很大,可以类似的离散
转移的话先说 O(m) 的:
f[v][j]=calc(i,j)to is vs sonmaxk=jf[to][k]
calc(i,j) 表示花费 j 的代价到i可以得到收益的最大值
预处理那个最大值即可 O(1) 转移
路径的话用存下的 f 值即可。

然而
第一次交发现自己每套记忆化搜索的壳,TLE
第二次交发现复杂度是O(nm2),TLE
然后睡觉去了。。
还是有些不自信啊

Code

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<time.h>
#include<stdlib.h>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
typedef double db;
typedef unsigned ud;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vec;
typedef vector<pii> vecp;

#define fi first 
#define se second
#define pb push_back
#define ph push
#define showtime fprintf(stderr,"time = %.15f\n",clock() / (double)CLOCKS_PER_SEC)

const int INF=(ud)-1>>1;
const ll inf=(ull)-1ll>>1;

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=1e3+5;
struct Edge{
    int to,id,nxt;
}G[M<<1];
int head[M],tot_edge;
inline void add_edge(int from,int to,int id){
    G[tot_edge]=(Edge){to,id,head[from]};
    head[from]=tot_edge++;
}
int c[M],b[M];
int Nod[M][M],sz[M],tmp[M];
int res[M];
vec ed[M];
int pot[M][M];
ll g[M][M],Mx[M][M];
inline void predfs(int v,int f){
    for(int i=head[v];~i;i=G[i].nxt){
        int to=G[i].to;
        if(to==f)continue;
        predfs(to,v);
        //Merge
        for(int j=1;j<=sz[v];++j)
            tmp[j]=Nod[v][j];
        int w=0,a=1,b=1;
        for(;a<=sz[v]&&b<=sz[to];){
            if(Nod[to][b]>tmp[a])
                Nod[v][++w]=tmp[a++];
            else Nod[v][++w]=Nod[to][b++];
        }
        for(;a<=sz[v];)Nod[v][++w]=tmp[a++];
        for(;b<=sz[to];)Nod[v][++w]=Nod[to][b++];
        sz[v]=w;
    }
    for(int i=head[v];~i;i=G[i].nxt){
        int to=G[i].to;
        if(to==f)continue;
        for(int l1=0,l2=0;l2<=sz[v];++l2){
            for(;Nod[to][l1]<Nod[v][l2]&&l1<=sz[to];++l1);
            pot[to][l2]=l1;
        }
    }
}//RT
inline ll dfs(int v,ll cost,int last,int f=0){
    ll &w=g[v][last];
    if(~w)return w;
    w=0;
    for(int i=0;i<ed[v].size();++i)
        if(ed[v][i]>=cost)w+=cost;
    for(int i=head[v];~i;i=G[i].nxt){
        int to=G[i].to;
        if(to==f)continue;
        if(~Mx[to][pot[to][last]])w+=Mx[to][pot[to][last]];
        else{
            Mx[to][sz[to]+1]=0;
            for(int j=sz[to];~j;--j){//枚举选几个 
                ll k=dfs(to,Nod[to][j],j,v);
                Mx[to][j]=max(k,Mx[to][j+1]);
            }
            w+=Mx[to][pot[to][last]];
        }
    }
    return w;
}
inline void rdfs(int v,ll cost,int f=0){
    for(int i=head[v];~i;i=G[i].nxt){
        int to=G[i].to;
        if(to==f)continue;
        ll mx=0;
        int w=0;
        for(int j=1;j<=sz[to];++j){
            if(Nod[to][j]<cost)continue;
            if(g[to][j]>mx)mx=g[to][j],w=j;
        }
        res[G[i].id]=max(0ll,Nod[to][w]-cost);
        rdfs(to,Nod[to][w],v);
    }
}
inline void gao(){
    memset(head,-1,sizeof(head));
    memset(sz,0,sizeof(sz));
    memset(g,-1,sizeof(g));
    memset(Mx,-1,sizeof(Mx));
    memset(pot,-1,sizeof(pot));
    tot_edge=0;
    int n,m;cin>>n>>m;
    for(int i=1;i<=n;++i)
        ed[i].clear();
    for(int i=1,u,v;i<n;++i){
        rd(u),rd(v);
        add_edge(u,v,i);
        add_edge(v,u,i);
    }
    for(int i=1;i<=m;++i){
        rd(c[i]),rd(b[i]);
        Nod[c[i]][++sz[c[i]]]=b[i];
        ed[c[i]].pb(b[i]);
    }
    for(int i=1;i<=n;++i)
        sort(Nod[i]+1,Nod[i]+sz[i]+1);
    predfs(1,0);
    cout<<dfs(1,0,0)<<endl;
    rdfs(1,0);
    for(int i=1;i<n-1;++i)
    pt(res[i]),putchar(' ');
    pt(res[n-1]);putchar('\n');
}
int main(){
    int _;
    for(cin>>_;_--;)gao();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值