题目描述:
题解:
裸的基环树直径。
代码:
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N = 1000050; template<typename T> inline void read(T&x) { T f = 1,c = 0;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){c=c*10+ch-‘0‘;ch=getchar();} x = f*c; } int n,hed[N],cnt=1; ll ans; struct EG { int to,nxt; ll w; }e[2*N]; void ae(int f,int t,ll w) { e[++cnt].to = t; e[cnt].nxt = hed[f]; e[cnt].w = w; hed[f] = cnt; } int sta[2*N],tl,rt; ll ste[N]; bool vis[N],cir[N],use[N]; int dfs0(int u,int pre) { if(vis[u]) { rt = u; return 1; } vis[u] = 1; for(int j=hed[u],now;j;j=e[j].nxt) { int to = e[j].to; if(j==pre)continue; if((now=dfs0(to,j^1))) { if(now==1) { sta[++tl] = u; ste[tl] = e[j].w; cir[u] = 1; if(u!=rt)return 1; } return 2; } } return 0; } int fa[N]; ll dp[N],sum[2*N],st[2*N],h,l,now; void bfs(int u) { h = 1,l = 0; st[++l] = u; use[u]=1; while(h<=l) { u = st[h++]; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(use[to]||cir[to])continue; use[to] = 1; fa[to] = u; st[++l] = to; } } for(int i=l;i>=1;i--) { u = st[i]; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(cir[to]||to==fa[u])continue; ll tmp = dp[to]+e[j].w; now = max(now,dp[u]+tmp); dp[u]=max(dp[u],tmp); } } } int main() { // freopen("tt.in","r",stdin); read(n); for(int f,w,i=1;i<=n;i++) { read(f),read(w); ae(f,i,w),ae(i,f,w); } for(int i=1;i<=n;i++)if(!use[i]) { tl=0;now=0; dfs0(i,0); for(int j=1;j<=tl;j++) bfs(sta[j]),sta[j+tl]=sta[j]; if(tl==1) { now = max(now,dp[sta[1]]+ste[1]); ans+=now; continue; } for(int j=1;j<=tl;j++)sum[j]=sum[j-1]+ste[j]; for(int j=1;j<=tl;j++)sum[j+tl]=sum[j+tl-1]+ste[j]; h = 1,l = 0; for(int j=1;j<=2*tl;j++) { while(h<l&&st[h]+tl<=j)h++; if(h<=l)now = max(now,dp[sta[j]]+sum[j]+dp[sta[st[h]]]-sum[st[h]]); while(h<l&&dp[sta[st[l]]]-sum[st[l]]<dp[sta[j]]-sum[j])l--; st[++l] = j; } ans+=now; } printf("%lld\n",ans); return 0; }
原文:https://www.cnblogs.com/LiGuanlin1124/p/10777132.html