一个人只会把球传给一个人
找连通块,找环;一个连通块内只有一个环;
球传到环内才会终止;
最大传球距离,一个环加上从环中的一个点出发的被传过来的距离;
枚举取最大
把入度为零的点存入队列中,开始向中间走,不断更新到被传球的人的最大传球距离,当前的人所传球的人入度–;
如果入度等于零了,就入队;
处于环中的点入度必定不为零;
找入度不为零的点,开始答案
假如枚举到环中当前点为i,则ans=max ( i所在环的大小+传到i的最大传球距离-在环中指向i的距离)
#include <iostream>
#include <cstdio>
#define LL long long
using namespace std;
const int N=5e5+10;
int ch,n,a[N],d[N],pred[N],in[N],st[N],top,l,f[N];
LL ans;
bool vis[N];
int read()
{
int s=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {s=s*10+c-'0';c=getchar();}
return f*s;
}
int main()
{
freopen("pass.in","r",stdin);
freopen("pass.out","w",stdout);
n=read();
for(int i=1;i<=n;i++){
a[i]=read();d[i]=read();
in[a[i]]++;
}
for(int i=1;i<=n;i++)
if(!in[i]) st[++top]=i;
while(l<top){
int v=st[++l];
if(f[v]+d[v]>f[a[v]]) f[a[v]]=f[v]+d[v];
if(--in[a[v]]==0) st[++top]=a[v];
}
for(int i=1;i<=n;i++)
if(in[i]&&!vis[i]){
int k=i;top=0;LL s=0;
do
{
st[++top]=k;
vis[k]=1;
pred[a[k]]=d[k];
s+=d[k];
k=a[k];
}
while(k!=i);
for(int j=1;j<=top;j++){
LL g=s+f[st[j]]-pred[st[j]];
if(g>ans) ans=g;
}
}
printf("%lld",ans);
return 0;
}