[GXOI/GZOI2019] 旅行者
非常套路的做法。
做法
做法
考虑直接将
那我们看到我们要求
那么最直接的做法是随机讲这
做法
做法
在这之前先引入一个概念二进制分组,因为要使
但值得注意的是本题的边为有向边,所以在划分时有可能把终点的
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#define x first
#define y second
#define mp make_pair
using namespace std;
const int N = 1e5 + 10, M = 5e5 + 10;
typedef long long ll;
typedef pair<ll,int> PLI;
const ll INF = 1e15;
struct node{
ll d;
int x, st;
bool operator > (const node& t) const
{
return d > t.d;
}
};
PLI d[N][2];
int v[N][2], head[N], ver[M], Next[M], edge[M], tot, n, m, k, a[N];
void add(int x, int y, int z)
{
ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot;
}
void dijkstra()
{
priority_queue <node, vector<node>, greater<node> > q;
for(int i = 1; i <= n; i++) v[i][0] = v[i][1] = 0, d[i][0] = d[i][1] = mp(INF, 0);
sort(a + 1, a + k + 1);
for(int i = 1; i <= k; i++)
{
if(a[i] == a[i - 1]) continue;
int x = a[i];
d[x][0] = mp(0ll, x);
q.push(node({0, x, x}));
}
while(!q.empty())
{
node top = q.top(); q.pop();
int x = top.x, st = top.st; ll dis = top.d;
if((v[x][0] && v[x][1]) || (v[x][0] && st == d[x][0].y)) continue;
if(!v[x][0])
{
v[x][0] = 1;
d[x][0] = mp(dis, st);
}
else
{
v[x][1] = 1;
d[x][1] = mp(dis, st);
}
for(int i = head[x]; i; i = Next[i])
{
int y = ver[i], z = edge[i];
PLI t = mp(dis + z, st);
if(t < d[y][0])
{
if(t.y != d[y][0].y) d[y][1] = d[y][0];
d[y][0] = t;
q.push(node({dis + z, y, st}));
}
else if(t < d[y][1] && st != d[y][0].y)
{
d[y][1] = t;
q.push(node({dis + z, y, st}));
}
}
}
}
int read()
{
int x = 0, t = 1; char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-') t = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * t;
}
int main()
{
int T = read();
while(T--)
{
tot = 0;
n = read(), m = read();k = read();
for(int i = 1; i <= n; i++) head[i] = 0;
for(int i = 1; i <= m; i++)
{
int x = read(), y = read(), z = read();
add(x, y, z);
}
for(int i = 1; i <= k; i++) a[i] = read();
dijkstra();
ll res = INF;
for(int i = 1; i <= k; i++) res = min(res, d[a[i]][1].x);
printf("%lld\n", res);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现