P8817 [CSP-S 2022] 假期计划 题解
思路#
看一眼数据范围。
发现是一道
由于题目中路径的长度只有
考虑预处理。
我们设
容易发现我们最多只需要处理出前四大的即可,因为需要不同的四个点。
这样,我们就相当于有了
复杂度:
有一个小细节,由于这道题的合法路径判断需要知道两点之间的距离,即全源最短路。
发现边权全部是一可以直接
但是我考场上不知道为什么没有想到写了一个全源最短路。
所以考场代码就变为了:
但
Code#
放一个考场代码。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2510;
int n , m , cnt , ans , f[N][4][2];
int k , s[N] , vis[N] , head[N] , dis[N][N];
struct edge
{
int to , nxt , val;
}e[100000];
inline int read()
{
int asd = 0 , qwe = 1; char zxc;
while(!isdigit(zxc = getchar())) if(zxc == '-') qwe = -1;
while(isdigit(zxc)) asd = asd * 10 + zxc - '0' , zxc = getchar();
return asd * qwe;
}
inline void add(int x , int y)
{
e[++cnt] = {y , head[x] , 1} , head[x] = cnt;
e[++cnt] = {x , head[y] , 1} , head[y] = cnt;
}
inline void dij(int s)
{
priority_queue<pair<int , int> , vector<pair<int , int> > , greater<pair<int , int> > > q;
q.push({0 , s}) , memset(dis[s] , 0x3f , sizeof dis[s]);
dis[s][s] = 0 , memset(vis , 0 , sizeof vis);
while(q.empty() == 0)
{
int x = q.top().second; q.pop();
vis[x] = 1;
for(int i = head[x];i;i = e[i].nxt)
{
if(dis[s][e[i].to] > dis[s][x] + e[i].val)
{
dis[s][e[i].to] = dis[s][x] + e[i].val;
if(!vis[e[i].to]) q.push({dis[s][e[i].to] , e[i].to});
}
}
}
}
inline bool check(int x , int y , int z)
{
int dis1 = dis[x][y] - 1;
int dis2 = dis[y][z] - 1;
return dis1 <= k && dis2 <= k;
}
inline bool check(int x , int y , int z , int u)
{
return (x != y && y != z && z != u && x != z && x != u && y != u);
}
inline void add(int x , int z , int id)
{
int flag = 4;
for(int i = 0;i < 4;i++)
if(f[x][i][1] < z)
{ flag = i; break; }
if(flag != 4)
{
for(int i = 3;i > flag;i--)
swap(f[x][i][1] , f[x][i - 1][1]),
swap(f[x][i][0] , f[x][i - 1][0]);
f[x][flag][1] = z , f[x][flag][0] = id;
}
}
signed main()
{
n = read() , m = read() , k = read();
for(int i = 2;i <= n;i++)
s[i] = read();
for(int i = 1;i <= m;i++)
{
int x = read() , y = read();
add(x , y);
}
for(int i = 1;i <= n;i++)
dij(i);
for(int i = 2;i <= n;i++)
for(int j = 2;j <= n;j++)
{
if(i == j) continue;
if(check(1 , i , j))
add(j , s[i] , i);
}
memset(vis , 0 , sizeof vis);
for(int i = 2;i <= n;i++)
for(int j = 2;j <= n;j++)
if(i != j && dis[i][j] - 1 <= k)
{
int sum = 0;
for(int k1 = 0;k1 <= 3;k1++)
{
if(!f[i][k1][0]) continue;
for(int k2 = 0;k2 <= 3;k2++)
{
if(!f[j][k2][0]) continue;
if(check(i , j , f[i][k1][0] , f[j][k2][0]))
sum = max(sum , s[i] + s[j] + f[i][k1][1] + f[j][k2][1]);
}
}
ans = max(ans , sum);
}
cout << ans << endl;
return 0;
}
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2510;
int n , m , cnt , ans , f[N][4][2];
int k , s[N] , vis[N] , head[N] , dis[N][N];
struct edge
{
int to , nxt , val;
}e[100000];
inline int read()
{
int asd = 0 , qwe = 1; char zxc;
while(!isdigit(zxc = getchar())) if(zxc == '-') qwe = -1;
while(isdigit(zxc)) asd = asd * 10 + zxc - '0' , zxc = getchar();
return asd * qwe;
}
inline void add(int x , int y)
{
e[++cnt] = {y , head[x] , 1} , head[x] = cnt;
e[++cnt] = {x , head[y] , 1} , head[y] = cnt;
}
inline void bfs(int s)
{
queue<int> q;
memset(dis[s] , 0x3f , sizeof dis[s]);
q.push(s) , dis[s][s] = 0;
while(q.empty() == 0)
{
int x = q.front(); q.pop();
for(int i = head[x];i;i = e[i].nxt)
if(dis[s][e[i].to] == 0x3f3f3f3f3f3f3f3f)
dis[s][e[i].to] = dis[s][x] + e[i].val,
q.push(e[i].to);
}
}
inline bool check(int x , int y , int z)
{
int dis1 = dis[x][y] - 1;
int dis2 = dis[y][z] - 1;
return dis1 <= k && dis2 <= k;
}
inline bool check(int x , int y , int z , int u)
{
return (x != y && y != z && z != u && x != z && x != u && y != u);
}
inline void add(int x , int z , int id)
{
int flag = 4;
for(int i = 0;i < 4;i++)
if(f[x][i][1] < z)
{ flag = i; break; }
if(flag != 4)
{
for(int i = 3;i > flag;i--)
swap(f[x][i][1] , f[x][i - 1][1]),
swap(f[x][i][0] , f[x][i - 1][0]);
f[x][flag][1] = z , f[x][flag][0] = id;
}
}
signed main()
{
n = read() , m = read() , k = read();
for(int i = 2;i <= n;i++)
s[i] = read();
for(int i = 1;i <= m;i++)
{
int x = read() , y = read();
add(x , y);
}
for(int i = 1;i <= n;i++)
bfs(i);
for(int i = 2;i <= n;i++)
for(int j = 2;j <= n;j++)
{
if(i == j) continue;
if(check(1 , i , j))
add(j , s[i] , i);
}
memset(vis , 0 , sizeof vis);
for(int i = 2;i <= n;i++)
for(int j = 2;j <= n;j++)
if(i != j && dis[i][j] - 1 <= k)
{
int sum = 0;
for(int k1 = 0;k1 <= 3;k1++)
{
if(!f[i][k1][0]) continue;
for(int k2 = 0;k2 <= 3;k2++)
{
if(!f[j][k2][0]) continue;
if(check(i , j , f[i][k1][0] , f[j][k2][0]))
sum = max(sum , s[i] + s[j] + f[i][k1][1] + f[j][k2][1]);
}
}
ans = max(ans , sum);
}
cout << ans << endl;
return 0;
}
作者:JiaY19
出处:https://www.cnblogs.com/JiaY19/p/16847497.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)