清北——传球接力(pass)

本文探讨了在一个特定的传球游戏中寻找最远传球路径的问题。通过构建图模型,利用连通块和环的概念,结合入度为零节点的枚举策略,实现了对最大传球距离的有效计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个人只会把球传给一个人
找连通块,找环;一个连通块内只有一个环;
球传到环内才会终止;
最大传球距离,一个环加上从环中的一个点出发的被传过来的距离;
枚举取最大
把入度为零的点存入队列中,开始向中间走,不断更新到被传球的人的最大传球距离,当前的人所传球的人入度–;
如果入度等于零了,就入队;
处于环中的点入度必定不为零;
找入度不为零的点,开始答案
假如枚举到环中当前点为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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值