标签:sed pac prot 节点 eve style \n 优化 change
题意:给定上一棵树,然后每条边有一个权值,然后每个点到 1 的距离有两种,第一种是直接回到1,花费是 dist(1, i)^2,还有另一种是先到另一个点 j,然后两从 j 向1走,当然 j 也可以再向 k,一直到1,但经过一个点,那么就会出多一个花费 p,问你每个点到 1 的最小距离的最大值是多少。
题解:dp【i】代表从1节点出发,向下传递到i节点的最小花费,dp[i]=min(dp[j]+dis[i]-dis[j])^2,j是从i到1链上的每一个点,很明显的斜率优化,dis[i]是i到根节点的距离
dp[i]+2*dis[i]dis[j]= dis[j]+dis[i]*dis[i]+dis[j]*dis[j];
b + k * x = y
需要注意的 是在dfs的时候要记录一下上一层的head和last和q[last+1],因为改变的只有最后覆盖的last+1,方便退回到原来的状态
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-12; const int N=100000+10,maxn=1000000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; vector<pair<int,ll> >v[N]; ll dis[N],dp[N],ans,P; int q[N],head,last; struct node{ int head,last; int id,change; }p[N]; inline ll x(int j) { return dis[j]; } inline ll y(int j) { return dp[j]+dis[j]*dis[j]; } inline double slope(int i,int j) { // printf("------%d %d\n", i, j); return (y(i)-y(j))/(x(i)-x(j)); } void dfsdis(int u,int f,ll val) { dis[u]=val; for(int i=0;i<v[u].size();i++) { int x=v[u][i].fi; if(x!=f)dfsdis(x,u,val+v[u][i].se); } // printf("%d %d\n",u,dis[u]); } void dfs(int u,int f) { for(int i=0;i<v[u].size();i++) { int x=v[u][i].fi; if(x!=f) { // for(int j=head;j<=last;j++)printf("%d ",q[j]);printf("%d\n",x); p[x].head=head,p[x].last=last; while(head<last&&slope(q[head],q[head+1])<2*dis[x])head++; int te=q[head]; dp[x]=dp[te]+(dis[x]-dis[te])*(dis[x]-dis[te])+P; // printf("%lld %d %lld\n",P,x,dp[x]); ans=max(ans,dp[x]); while(head<last&&slope(q[last-1],q[last])>slope(q[last],x))last--; p[x].id=last+1,p[x].change=q[last+1]; q[++last]=x; dfs(x,u); head=p[x].head,last=p[x].last; q[p[x].id]=p[x].change; // for(int j=head;j<=last;j++)printf("%d ",q[j]);printf("%d\n",x); } } } int main() { int T;scanf("%d",&T); while(T--) { int n; scanf("%d%d",&n,&P); for(int i=1;i<=n;i++)v[i].clear(); for(int i=1;i<n;i++) { int u,vv;ll w; scanf("%d%d%lld",&u,&vv,&w); v[u].pb(mp(vv,w)); v[vv].pb(mp(u,w)); } dfsdis(1,-1,0); head=1,last=1;q[head]=1;dp[1]=-P; ans=0; dfs(1,-1); printf("%lld\n",ans); } return 0; } /*********************** 3 6 10 1 2 4 2 3 5 1 4 3 4 5 3 5 6 3 ***********************/
HDU - 59562016ACM/ICPC亚洲区沈阳站I - The Elder 树上斜率优化dp
标签:sed pac prot 节点 eve style \n 优化 change
原文地址:https://www.cnblogs.com/acjiumeng/p/8984659.html