题解 P4381 【[IOI2008]Island】
分析
其实就是一个基环树森林,求每棵树的直径之和
用的\(vector\),常数巨大
艰辛而曲折的卡常之路
Code
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define re register int
using namespace std;
inline int read()
{
int ans=0;
char last=' ',ch=getchar();
while(ch<'0'||ch>'9')
{
last=ch;ch=getchar();
}
while(ch>='0'&&ch<='9')
{
ans=(ans<<3)+(ans<<1);
ans+=ch-'0';ch=getchar();
}
return last=='-'?-ans:ans;
}
inline long long Max(long long a,long long b)
{
return a>b?a:b;
}
struct edge
{
int to;
long long dis;
int F;
edge(int tt,long long dd,int FF):to(tt),dis(dd),F(FF){}
};
long long dp[2000010],s[1000010],d[1000010],ANS,ans,ans2,ans3;
int n,ip1,ip2,st,cnt,CNT,vis[1000010],V[1000010],r[1000010];
vector<edge>a[1000010];
deque<int>q;
inline void Get_len(int now)
{
vis[now]=1;
for(re i=0;i<a[now].size();++i)
{
register edge T=a[now][i];
if(vis[T.to])
{
continue;
}
Get_len(T.to);
ANS=max(ANS,d[now]+d[T.to]+T.dis);
d[now]=max(d[now],d[T.to]+T.dis);
}
}
inline int DFS(int now,int las)
{
if(V[now]==1)
{
V[now]=2;
r[++cnt]=now;
vis[now]=1;
return 1;
}
V[now]=1;
for(re i=0;i<a[now].size();++i)
{
register edge T=a[now][i];
if(las!=T.F&&DFS(T.to,T.F))
{
if(V[now]!=2)
{
r[++cnt]=now;
vis[now]=1;
s[cnt]=s[cnt-1]+T.dis;
}
else
{
s[st-1]=s[st]-T.dis;
return 0;
}
return 1;
}
}
return 0;
}
inline long long BFS(int root)
{
st=cnt+1,ans2=0,ans3=0;
DFS(root,0);
for(re i=st;i<=cnt;++i)
{
ANS=0;
Get_len(r[i]);
ans2=Max(ans2,ANS);
dp[i+cnt-st+1]=dp[i]=d[r[i]];
s[i+cnt-st+1]=s[i+cnt-st]+s[i]-s[i-1];
}
while(!q.empty())
q.pop_back();
for(re i=st;i<=2*cnt-st+1;++i)
{
while(!q.empty()&&q.front()<=i-cnt+st-1)
q.pop_front();
if(!q.empty())
ans3=Max(ans3,dp[i]+dp[q.front()]+s[i]-s[q.front()]);
while(!q.empty()&&dp[q.back()]-s[q.back()]<=dp[i]-s[i])
q.pop_back();
q.push_back(i);
}
return Max(ans2,ans3);
}
int main()
{
n=read();
for(re i=1;i<=n;++i)
{
ip1=read();
ip2=read();
a[i].push_back(edge(ip1,ip2,++CNT));
a[ip1].push_back(edge(i,ip2,CNT));
}
for(re i=1;i<=n;++i)
{
if(!vis[i])
{
ans+=BFS(i);
}
}
printf("%lld",ans);
}