日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[IOI2008]Island

發布時間:2025/4/9 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [IOI2008]Island 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目大意:

找基環樹直徑

(這個題輸入給出的是內向基環樹(雖然是無向邊))

?

存在兩種情況:

1.直徑在樹上。

2.直徑從樹里走到環上,再走進另外一個樹里。

?

首先dfs找到環。

第一種直接樹形dp。dp[i]i往下最長路徑。還能用來求第二種情況。

第二種,找到環之后,斷環成鏈,復制一倍。求的是,選擇距離小于環長的兩個點,貢獻是兩個點的dp[i],和兩個點之間的距離。這個用單調隊列優化dp即可。

?

bzoj會爆棧mmp

如果你是ywy可以bfs求樹形dp

其實,這是一個內向基環樹,所以,直接topo排序,從葉子往上面topo

即可求得dp,還能求得環。

?

代碼:(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 */

?

轉載于:https://www.cnblogs.com/Miracevin/p/9903327.html

總結

以上是生活随笔為你收集整理的[IOI2008]Island的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。