JAG Practice Contest for ACM-ICPC Asia Regional 2016.K.Non-redundant Drive(点分治)
生活随笔
收集整理的這篇文章主要介紹了
JAG Practice Contest for ACM-ICPC Asia Regional 2016.K.Non-redundant Drive(点分治)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Atcoder
vjudge
這標(biāo)題好長...
\(Description\)
給定一棵\(n\)個點(diǎn)的樹。在每個點(diǎn)\(i\)你可以補(bǔ)充\(g_i\)的油量,經(jīng)過一條邊需要花費(fèi)邊長的油量。你可以選擇從任意一個點(diǎn)出發(fā),任意在樹上走直到油量耗盡或不能走(不能重復(fù)經(jīng)過同一個點(diǎn))。求最多能經(jīng)過多少個點(diǎn)。
\(n\leq10^5\)。
\(Solution\)
點(diǎn)分治。對每個分治重心\(rt\),求出從\(rt\)到子樹內(nèi)某個點(diǎn)至少需要多少初始油量、從子樹內(nèi)某個點(diǎn)到\(rt\),會剩下多少油量。然后sort一下合并即可。注意不要合并來自同一棵子樹內(nèi)的路徑,記兩個來自不同子樹的最大值就行了。
//129ms 14336KB #include <cstdio> #include <cctype> #include <algorithm> //#define gc() getchar() #define MAXIN 400000 #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) typedef long long LL; const int N=1e5+5,INF=1<<30;int Ans,Enum,H[N],nxt[N<<1],to[N<<1],len[N<<1],A[N],Min,root,sz[N],cnt1,cnt2; bool vis[N]; char IN[MAXIN],*SS=IN,*TT=IN; struct Node {int s,dep,bel;bool operator <(const Node &x)const{return s<x.s;//按s排序啊(我怎么按dep了mdzz)} }f[N],g[N];inline int read() {int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-48,c=gc());return now; } inline void AE(int w,int u,int v) {to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, len[Enum]=w;to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, len[Enum]=w; } void FindRoot(int x,int fa,int tot) {int mx=0; sz[x]=1;for(int i=H[x],v; i; i=nxt[i])if(!vis[v=to[i]]&&v!=fa) FindRoot(v,x,tot), sz[x]+=sz[v], mx=std::max(mx,sz[v]);mx=std::max(mx,tot-sz[x]);if(mx<Min) Min=mx, root=x; } void DFS(int x,int fa,int need,int need2,int sum,int dep,int anc) {//need:v->x當(dāng)前點(diǎn)至少需要要有多少油量 rest:v->x會剩下多少油量 need2:x->v最少需要多少起始油量 sum:x->v一共多少油量 rest=A[root]+sumg[++cnt2]=(Node){need2,dep,anc}, sum+=A[x];if(A[x]>=need) f[++cnt1]=(Node){sum,dep+1,anc};for(int i=H[x],v,w; i; i=nxt[i])if(!vis[v=to[i]]&&v!=fa)w=len[i], DFS(v,x,w+std::max(0,need-A[x]),std::max(need2,w-sum),sum-w,dep+1,anc); } void Solve(int x) {vis[x]=1, cnt1=cnt2=1, f[1]=(Node){0,1,0}, g[1]=(Node){0,0,0};for(int i=H[x],v; i; i=nxt[i])if(!vis[v=to[i]]) DFS(v,x,len[i],len[i],-len[i],1,v);for(int i=1,a=A[x]; i<=cnt1; ++i) f[i].s+=a;std::sort(f+1,f+1+cnt1), std::sort(g+1,g+1+cnt2);Node a=(Node){0,0,0},b=a;int res=0; g[cnt2+1].s=INF;for(int i=1,j=1; i<=cnt1; ++i){while(g[j].s<=f[i].s){if(g[j].dep>a.dep)if(g[j].bel!=a.bel) b=a, a=g[j];else a=g[j];else if(g[j].dep>b.dep && g[j].bel!=a.bel) b=g[j];++j;}if(f[i].bel!=a.bel) res=std::max(res,f[i].dep+a.dep);else res=std::max(res,f[i].dep+b.dep);}Ans=std::max(Ans,res);for(int i=H[x],v; i; i=nxt[i])if(!vis[v=to[i]]) Min=N, FindRoot(v,x,sz[v]), Solve(root); }int main() {int n=read();for(int i=1; i<=n; ++i) A[i]=read();for(int i=1; i<n; ++i) AE(read(),read(),read());Ans=1, Min=N, FindRoot(1,1,n), Solve(root), printf("%d\n",Ans);return 0; }
轉(zhuǎn)載于:https://www.cnblogs.com/SovietPower/p/10576150.html
總結(jié)
以上是生活随笔為你收集整理的JAG Practice Contest for ACM-ICPC Asia Regional 2016.K.Non-redundant Drive(点分治)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2019年春季学期第四周作业
- 下一篇: web中静态资源和动态资源的概念及区别