85分红绿紫
查看原帖
85分红绿紫
315205
Kniqht楼主2023/10/3 22:54

rt,悬赏两个关注+膜拜大佬

第一篇题解的思路,写法非常通俗。f[i][0/1/2]表示从i出发在k+1长度以内能达到的最大/次大/次次大的节点权值

ok(i,j)判断i在k+1步内能否到j

bfs n遍预处理,双重循环判断

#include<bits/stdc++.h>
#define PII pair<int,int>
#define fir first
#define sec second
#define ll long long
using namespace std;
const int N=2510;
int n,m,k;
bool g1[N][N];ll g[N][N];
ll f[N][3],w[N];
PII q[N];bool st[N];
bool ok(int x,int y){
	return g[x][y]<=k+1;
}
void Bfs(int sta){
	memset(st,0,sizeof(st));
	int hh=0,tt=-1;
	q[++tt]={sta,0};
	while(hh<=tt){
		PII t=q[hh++];
		int ver=t.fir,dis=t.sec;
		if(dis>k) break;	
		if(st[ver]) continue;
		st[ver]=1;
		for(int i=1;i<=n;i++)
			if(g1[ver][i]&&!st[i]){
				g[sta][i]=dis+1;
				q[++tt]={i,dis+1};
				if(sta==1||!ok(1,i)) continue;
				if(i!=1&&w[i]>=w[f[sta][0]]) f[sta][2]=f[sta][1],f[sta][1]=f[sta][0],f[sta][0]=i;
				else if(i!=1&&w[i]>=w[f[sta][1]]) f[sta][2]=f[sta][1],f[sta][1]=i;
				else if(i!=1&&w[i]>w[f[sta][2]]) f[sta][2]=i;
			}
	}
}
signed main(){
	memset(g,0x3f,sizeof(g));
	scanf("%d%d%d",&n,&m,&k);
	for(int i=2;i<=n;i++) scanf("%lld",&w[i]);
	w[0]=-1e18;
	while(m--){
		int a,b;scanf("%d%d",&a,&b);
		g1[a][b]=g1[b][a]=1;
	}
	for(int i=1;i<=n;i++) Bfs(i);
	ll ans=0;
	for(int i=2;i<=n;i++)
		for(int j=2;j<=n;j++){
			if(i==j||!ok(i,j)) continue;
			for(int c1=0;c1<3;c1++)
				for(int c2=0;c2<3;c2++){
					if(f[i][c1]!=j&&f[j][c2]!=i&&f[i][c1]!=f[j][c2]&&f[i][c1]!=i&&f[j][c2]!=j) 
						ans=max(ans,w[i]+w[j]+w[f[i][c1]]+w[f[j][c2]]);
				}
		} 
	printf("%lld",ans);
    return 0;
}
2023/10/3 22:54
加载中...