[模板] 最短路树
[模板] 最短路树
概念类
定义构建一棵树,使得树上任意不属于根的节点
, 原图走到 的最短路。
显然在跑
这棵树的边数为
图片来自@Lis~
题意
给一个
个点, 条边的无向简单带权连通图, 要求删边至最多剩余 条边. 定义"好点"是指删边后, 1号节点到它的最短路长度仍然等于原图最短路长度的节点.
最大化删边后的好点个数。
做法
显然,这保留的
所以这是一道求最短路树的模板。
首先考虑如何判断一条边是否在最短路树上。
- 每次跑最短路的时候记录一下。
if(!vis[v] && dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
pre[v]=id;//记录边的id
q.push(mp(dis[v],v));
}
- 直接判断
if(dis[v]==dis[u]+e[i].w){
//...
}
目测两种都可以过 CF 评测这么神奇
显然一棵最短路树可以有很多种形态,但是对这道题来说不用犹豫。
所以可以直接这么写:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long
template <typename T>
inline T read(){
T x=0;char ch=getchar();bool fl=false;
while(!isdigit(ch)){if(ch=='-')fl=true;ch=getchar();}
while(isdigit(ch)){
x=(x<<3)+(x<<1)+(ch^48);ch=getchar();
}
return fl?-x:x;
}
const int maxn = 3e5 + 10;
int head[maxn],cnt=0;
struct edge{
int to,nxt;LL w;
int id;
}e[maxn<<1];
inline void link(int u,int v,LL w){
e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;e[cnt].w=w;
}
bool vis[maxn];
int n,m,k,tot;
LL dis[maxn];
int pre[maxn];
#include <queue>
#define mp make_pair
#define Pair pair<long long,int>
void dij(int s){
priority_queue <Pair,vector<Pair>,greater<Pair> > q;
memset(dis,0x3f,sizeof dis);
dis[s]=0LL;q.push(mp(0,s));
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u])continue;
vis[u]=true;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to,id=e[i].id;
if(!vis[v] && dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
pre[v]=id;q.push(mp(dis[v],v));
}
}
}
}
#define read() read<int>()
int ans[maxn],top=0;
void dfs(int u){
if(tot>=k)return ;
vis[u]=true;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to,id=e[i].id;
if(vis[v])continue;
if(dis[v]==dis[u]+e[i].w){
ans[++top]=id;
tot++;
dfs(v);
if(tot>=k)return ;
}
}
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++){
int u,v;LL w;
scanf("%d%d%lld",&u,&v,&w);
link(u,v,w);e[cnt].id=i;
link(v,u,w);e[cnt].id=i;
}
dij(1);
//
//cerr<<"dises:\n";
//for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
//cerr<<endl;
//
memset(vis,false,sizeof vis);
printf("%d\n",min(n-1,k));
dfs(1);
for(int i=1;i<=top;i++)printf("%d ",ans[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~