Shortcut G
题面
首先要明白一个事情,虽然某次考试考场上我就已经推出来这个结论了,但很遗憾,那次考试没用上,而过了这么久,在这道题里偶然遇见,甚是惊喜。
其实也没什么,最短路跑出来的结果一定是一棵树,至少用迪杰斯特拉算法跑出来的结果肯定是一棵树。为什么?你看它的算法流程就知道了。这个算法就是尝试在已经确定的点集里挑一个,然后尝试更新其它点。换个描述方法就是在已经生成的这棵树里挑选一个叶子节点,将一些树外节点作为它的儿子加入树中(个人观点如果有错敬请原谅)。
于是就可以做这道题了。首先把最短路树建出来,做到这一点只需在跑最短路的时候记录一下由哪个节点更新到它就可以了。于是题目中的加一条奇怪边的操作就等价于把树上某个节点和根节点连起来。然后考虑对于树上的一个节点,加入把它和根节点用一条长度为
那么这样做,减少的路径是多少呢?明显最后需要达到的效果是所有能走捷径的牛都会走捷径,不然这条路就没有意义了。得出结论,假如在节点
码风清奇,见谅。
#include<cstdio>
#include<cstring>
#include<queue>
//#define zczc
#define int long long
using namespace std;
const int N=10010;
const int M=50010;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar(); }
wh*=f;return;
}
inline int max(int s1,int s2){
return s1<s2?s2:s1;
}
int m,n,cost;
namespace g{
struct edge{
int t,v,next;
}e[M<<1];
int esum,head[N];
inline void add(int fr,int to,int val){
esum++;
e[esum].t=to;
e[esum].v=val;
e[esum].next=head[fr];
head[fr]=esum;
return;
}
int dis[N],to[N],va[N];
bool vis[N];
struct node{
int wh,dis;
};
bool operator <(node s1,node s2){
return s2.dis<s1.dis;
}
priority_queue<node>q;
void solve(){
int s1,s2,s3;
for(int i=1;i<=n;i++){
read(s1);read(s2);read(s3);
add(s1,s2,s3);add(s2,s1,s3);
}
memset(dis,0x3f,sizeof(dis));
dis[1]=0;q.push((node){1,0});
while(!q.empty()){
int wh=q.top().wh,nd=q.top().dis;q.pop();
if(vis[wh])continue;vis[wh]=true;
for(int i=head[wh],th;i;i=e[i].next){
th=e[i].t;
if(dis[wh]+e[i].v<dis[th]){
dis[th]=dis[wh]+e[i].v,to[th]=wh,va[th]=e[i].v;
q.push((node){th,dis[th]});
}
if(dis[wh]+e[i].v==dis[th]&&wh<to[th]){
to[th]=wh,va[th]=e[i].v;
}
}
//printf("now:%lld\n",wh);
//for(int i=1;i<=m;i++)printf("%lld %lld\n",dis[i],to[i]);
}
return;
}
}
namespace t{
int a[N],len[N],size[N];
struct edge{
int t,v,next;
}e[N<<1];
int esum,head[N];
inline void add(int fr,int to,int val){
esum++;
e[esum].t=to;
e[esum].v=val;
e[esum].next=head[fr];
head[fr]=esum;
return;
}
void build(int wh,int fa,int nlen){
size[wh]=a[wh];len[wh]=nlen;
for(int i=head[wh],th;i;i=e[i].next){
th=e[i].t;if(th==fa)continue;
build(th,wh,nlen+e[i].v);
size[wh]+=size[th];
}
return;
}
void solve(){
for(int i=2;i<=m;i++){
add(i,g::to[i],g::va[i]);
add(g::to[i],i,g::va[i]);
}
build(1,0,0);
int ans=0;
for(int i=1;i<=m;i++)ans=max(ans,(len[i]-cost)*size[i]);
printf("%lld",ans);
}
}
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
read(m);read(n);read(cost);
for(int i=1;i<=m;i++)read(t::a[i]);
g::solve();
t::solve();
return 0;
}
一如既往,万事胜意
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具