[IOI2008]Island
生活随笔
收集整理的這篇文章主要介紹了
[IOI2008]Island
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目大意:
找基環(huán)樹直徑
(這個題輸入給出的是內(nèi)向基環(huán)樹(雖然是無向邊))
?
存在兩種情況:
1.直徑在樹上。
2.直徑從樹里走到環(huán)上,再走進另外一個樹里。
?
首先dfs找到環(huán)。
第一種直接樹形dp。dp[i]i往下最長路徑。還能用來求第二種情況。
第二種,找到環(huán)之后,斷環(huán)成鏈,復制一倍。求的是,選擇距離小于環(huán)長的兩個點,貢獻是兩個點的dp[i],和兩個點之間的距離。這個用單調(diào)隊列優(yōu)化dp即可。
?
bzoj會爆棧mmp
如果你是ywy可以bfs求樹形dp
其實,這是一個內(nèi)向基環(huán)樹,所以,直接topo排序,從葉子往上面topo
即可求得dp,還能求得環(huán)。
?
代碼:(dfs爆棧版)
#pragma comment(linker, "/STACK:102400000,102400000") #include<bits/stdc++.h> #define il inline #define reg register int #define numb (ch^'0') using namespace std; typedef long long ll; void rd(int &x){char ch;x=0;while(!isdigit(ch=getchar()));for(x=numb;isdigit(ch=getchar());x=x*10+numb); } namespace Miracle{ const int N=1e6+5; int n; struct node{int nxt,to;ll val; }e[2*N]; int hd[N],cnt=1; void add(int x,int y,int z){e[++cnt].nxt=hd[x];e[cnt].to=y;e[cnt].val=z;hd[x]=cnt; } bool vis[N]; bool on[N];//on the huan bool in[N]; int to[N],v[N]; int sta[N],top; int len;//huan chang int mem[2*N],tot; ll cos[2*N]; int q[2*N],l,r; ll f[N]; ll ans; ll sum; ll zhi; bool fl; void dfs(int x,int in_edge){ // cout<<" dfs "<<x<<" "<<fl<<" "<<top<<endl;vis[x]=1;sta[++top]=x;for(reg i=hd[x];i;i=e[i].nxt){int y=e[i].to;if(i==(in_edge^1)) continue;if(!vis[y]){dfs(y,i);}else if(!fl){fl=true;// cout<<" find "<<top<<" : "<<sta[top]<<endl;int z;do{z=sta[top];on[z]=1;mem[++len]=z;top--;}while(z!=y);}}if(sta[top]==x) --top;//warning!!! } void dp(int x,int fa){//find farthestfor(reg i=hd[x];i;i=e[i].nxt){int y=e[i].to;if(y==fa) continue;if(on[y]) continue;dp(y,x);zhi=max(zhi,f[x]+e[i].val+f[y]);f[x]=max(f[x],e[i].val+f[y]);} } ll wrk(int st){sum=0;len=0;fl=false;top=0;dfs(st,0);for(reg i=1;i<=len;++i){zhi=0;dp(mem[i],0);sum=max(sum,zhi);mem[i+len]=mem[i];}l=1,r=0;cos[1]=0;for(reg i=2;i<=2*len;++i){cos[i]=(to[mem[i]]==mem[i-1])?v[mem[i]]:v[mem[i-1]];cos[i]+=cos[i-1];}for(reg i=1;i<=2*len;++i){while(l<=r&&i-q[l]>=len) ++l;if(i!=1) sum=max(sum,f[mem[q[l]]]-cos[q[l]]+cos[i]+f[mem[i]]);while(l<=r&&f[mem[q[r]]]-cos[q[r]]<=f[mem[i]]-cos[i]) --r;q[++r]=i;}return sum; } int main(){rd(n);int x;int z;for(reg i=1;i<=n;++i){rd(x);rd(z);to[i]=x;v[i]=z;add(i,x,z);add(x,i,z);}for(reg i=1;i<=n;++i){if(!vis[i]){ans+=wrk(i);}}printf("%lld",ans);return 0; }} int main(){Miracle::main();return 0; }/*Author: *Miracle*Date: 2018/11/4 9:27:26 */?
轉(zhuǎn)載于:https://www.cnblogs.com/Miracevin/p/9903327.html
總結(jié)
以上是生活随笔為你收集整理的[IOI2008]Island的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PXE自动化装机(4)
- 下一篇: 【DP、线段树优化】琪露诺