社区讨论
80pts爆掉7个点求助
P8817[CSP-S 2022] 假期计划参与者 2已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @m2lt74ia
- 此快照首次捕获于
- 2024/10/23 19:46 去年
- 此快照最后确认于
- 2025/11/04 16:25 4 个月前
数据点7输出结果:2908964088953073518
正确结果:201920764
怀疑哪个地方爆了,但没调出来
CPP/*
找到一条路径1-A-B-C-D-1构成环
由于是无向图,根据环的对称性,可以拆成1-A-B和C-D-1(1-D-C)两条路径
1点是确定的,接下来只需要枚举B,C两点找最大值;
当B点是定点,A点就好求了:满足题意的点中找权值最大的点
注意:考虑到A点可能与D,C两点重合,因此需要求出前三大的1-A-B路径
即A与1、B相连且距离<=k+1的所有点中,点值最大的前三个
预处理b[i][3]记录与1和i相连{点值最大}的前三个点,考虑大根堆或直接分类讨论或排序(注意记录的是点)
转成k次,即两点间长度为k+1,就是要满足任意两点距离<=k+1
*/
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
int k,n,m;
long long w[3000]; //点的权值,w[1]=0
vector<int> e[3000]; //存每条边桐乡的下一个点,见一个邻接表
long long ans;
int dis[2600][2600]; //dis[i][j]表示从i点到j点的最短距离
int b[2600][5];
void bfs(int s) //求s点到其他点的距离
{
for(int i=1;i<=n;i++) dis[s][i]=-1; //在这里初始化能优化时间
queue<int> q;
q.push(s);
dis[s][s]=0;
while(!q.empty())
{
int t=q.front();
q.pop();
if(dis[s][t]>=k+1) continue; //题目限定两点间的直接距离<=k+1,其他都视为无法到达(注意是>=k+1)
for(vector<int>::iterator it=e[t].begin();it!=e[t].end();it++)
if(dis[s][*it]==-1) //如果*it这个点还没有被更新,就更新并入队,因为逐层扩散,先扩散到的一定最短,不用再比较了
{
dis[s][*it]=dis[s][t]+1;
q.push(*it);
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=2;i<=n;i++)
scanf("%lld",&w[i]);
int u,v;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
//如果使用转乘,剩余次数减一,下一个点不加权值
for(int i=1;i<=n;i++) bfs(i); //每个点都bfs
//预处理b[][](不需要再判断dis<=k了,因为>k已经被视为无法到达)
for(int i=2;i<=n;i++) //定下B
{
int p1=0,p2=0,p3=0; //依次记录A的分数值最大,次大,次次大的点
for(int j=2;j<=n;j++) //枚举A
{
if(i==j) continue; //b[i][]!=i
if(dis[1][j]==-1 || dis[j][i]==-1) continue;
if(w[j]>w[p1]) p3=p2,p2=p1,p1=j;
else if(w[j]>w[p2]) p3=p2,p2=j;
else if(w[j]>w[p3]) p3=j; //记录点的序号
}
b[i][0]=p1,b[i][1]=p2,b[i][2]=p3;
}
for(int i=2;i<n;i++) //枚举B
for(int j=i+1;j<=n;j++) //枚举C(不妨设C>B)
{
if(dis[i][j]==-1) continue; //大范围枚举一定注意要有路径
for(int k=0;k<3;k++)
for(int l=0;l<3;l++) //已知C!=B,已经判断b[i][]!=i,还要满足A!=C,D,1;C!=A,B,1
if(b[j][l]!=j && b[i][k]!=i && b[i][k]!=b[j][l] && b[i][k]!=1 && b[j][l]!=1 && b[i][k]!=j && b[j][l]!=i )
ans=max( ans,w[i]+w[j]+w[b[i][k]]+w[b[j][l]] );
}
printf("%lld",ans);
}
回复
共 2 条回复,欢迎继续交流。
正在加载回复...