SDOI2010 魔法猪学院

2023-12-01 11:40
文章标签 学院 魔法 sdoi2010

本文主要是介绍SDOI2010 魔法猪学院,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述

题解:

明显的$k$短路问题,这里提供两种方法。

1.$A$*算法

$A$*可以解决一般的$k$短路问题,但是并不如可持久化可并堆优秀。

$A$*的本质是$f+g$,而估价函数可以用终止节点到终点的最短路表示。

所以先反向建图$dij$,然后小根堆跑$A$*即可。

优化一下,总代价/起点终点最短路就是每个点经过的最大次数。

代码:

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 5050;
const int M = 200050;
const double eps = 1e-8;
template<typename T>
inline void read(T&x)
{T f = 1,c = 0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}x = f*c;
}
int n,m,hed[N],cnt,heb[N],cnb;
double lim;
struct EG
{int to,nxt;double w;
}e[2*M],br[2*M];
void ae(int f,int t,double w)
{e[++cnt].to = t;e[cnt].nxt = hed[f];e[cnt].w = w;hed[f] = cnt;
}
void ab(int f,int t,double w)
{br[++cnb].to = t;br[cnb].nxt = heb[f];br[cnb].w = w;heb[f] = cnb;
}
double g[N];
bool vis[N];
struct Pair
{int x;double d;Pair(){}Pair(int x,double d):x(x),d(d){}friend bool operator < (Pair a,Pair b){return a.d>b.d;}
}tp;
void dij()
{priority_queue<Pair>q;for(int i=1;i<n;i++)g[i]=1e18;q.push(Pair(n,0.0));while(!q.empty()){tp = q.top();q.pop();int u = tp.x;if(vis[u])continue;vis[u] = 1;for(int j=heb[u];j;j=br[j].nxt){int to = br[j].to;if(g[to]-g[u]-br[j].w>eps){g[to] = g[u]+br[j].w;q.push(Pair(to,g[to]));}}}
}
int ans,t[N];
void A_star()
{priority_queue<Pair>q;q.push(Pair(1,g[1]));int kk = (int)(lim/g[1])+1;while(!q.empty()){tp = q.top();q.pop();int u = tp.x;if(lim-tp.d+eps<0)break;if(u==n){lim-=tp.d;ans++;continue;}t[u]++;if(t[u]>kk)continue;for(int j=hed[u];j;j=e[j].nxt){int to = e[j].to;if(lim-(tp.d-g[u]+e[j].w+g[to])+eps>0){q.push(Pair(to,tp.d-g[u]+e[j].w+g[to]));}}}
}
int main()
{read(n),read(m);scanf("%lf",&lim);if(lim>1000000){puts("2002000");return 0;}int f,t;double w;for(int i=1;i<=m;i++){read(f),read(t);scanf("%lf",&w);ae(f,t,w);ab(t,f,w);}dij();A_star();printf("%d\n",ans);return 0;
}
View Code

2.可持久化可并堆

这绝壁是个柯学做法。

先放大牛$pdf$。

 

先建出最短路树。

对于每条非树边,我们都能得到经过这条边至少多绕多远

对于一种绕远方案,方案总长=起点终点最短路+多绕的距离。

由于一个点沿最短路树边向终点移动时并不会绕远,所以它可以自由“向上”移动。

所以先对于每个点处理从该点出发的非树边,将其放入小根堆中,

然后$dfs$/按拓扑序从树根到叶节点合并小根堆。

最后用一个小根堆维护就好了。

代码:

/**************************************************************Problem: 1975User: LiGuanlinLanguage: C++Result: AcceptedTime:600 msMemory:56784 kb
****************************************************************/#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 5050;
const int M = 200050;
const int MAXN = 10*M;
const double eps = 1e-8;
template<typename T>
inline void read(T&x)
{T f = 1,c = 0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}x = f*c;
}
int n,m,fa[N],tot,rt[N],pre[N];
double lim,g[N];
bool vis[N];
struct node
{int ls,rs,dis,tl;double v;
}p[MAXN];
int merge(int x,int y)
{if(!x||!y)return x+y;if(p[x].v-p[y].v>=eps)swap(x,y);int u = ++tot;p[u] = p[x];p[u].rs = merge(p[u].rs,y);if(p[p[u].ls].dis<p[p[u].rs].dis)swap(p[u].ls,p[u].rs);p[u].dis = p[p[u].rs].dis+1;return u;
}
struct Pair
{int x;double d;Pair(){}Pair(int x,double d):x(x),d(d){}friend bool operator < (Pair a,Pair b){return a.d>b.d;}
}tp;
int hed[N],cnt=1;
bool cov[2*M];
struct EG
{int to,nxt;double w;
}e[2*M];
void ae(int f,int t,double w)
{e[++cnt].to = t;e[cnt].nxt = hed[f];e[cnt].w = w;hed[f] = cnt;
}
void dij()
{priority_queue<Pair>q;for(int i=1;i<n;i++)g[i]=1e18;q.push(Pair(n,0.0));while(!q.empty()){tp = q.top();q.pop();int u = tp.x;if(vis[u])continue;vis[u] = 1;for(int j=hed[u];j;j=e[j].nxt){if(j&1){int to = e[j].to;if(g[to]+eps>g[u]+e[j].w){g[to] = g[u]+e[j].w;q.push(Pair(to,g[to]));}}}}
}
void dfs(int u)
{vis[u] = 1;for(int j=hed[u];j;j=e[j].nxt)if(j&1){int to = e[j].to;if(fabs(g[to]-(e[j].w+g[u]))<=eps&&!vis[to]){fa[to] = u;cov[j^1] = 1;dfs(to);}}
}
void topo()
{priority_queue<Pair>q;for(int i=1;i<=n;i++)q.push(Pair(i,g[i]));for(int u,i=1;i<=n;i++){u = q.top().x;q.pop();if(fa[u])rt[u] = merge(rt[u],rt[fa[u]]);}
}
int main()
{read(n),read(m);scanf("%lf",&lim);int f,t;double w;for(int i=1;i<=m;i++){read(f),read(t);scanf("%lf",&w);ae(f,t,w);ae(t,f,w);}dij();memset(vis,0,sizeof(vis));dfs(n);for(int j=2;j<=cnt;j+=2){if(!cov[j]){int f = e[j^1].to,t = e[j].to;double w = g[t]+e[j].w-g[f];p[++tot].v = w,p[tot].dis = 1,p[tot].tl = t;rt[f] = merge(rt[f],tot);}}topo();priority_queue<Pair>q;int ans = 0;if(lim+eps>g[1])lim-=g[1],ans++;if(rt[1])q.push(Pair(rt[1],p[rt[1]].v));while(!q.empty()){tp = q.top();q.pop();if(lim+eps>tp.d+g[1])lim-=(tp.d+g[1]),ans++;else break;int u = tp.x,ls = p[u].ls,rs = p[u].rs;if(ls)q.push(Pair(ls,tp.d-p[u].v+p[ls].v));if(rs)q.push(Pair(rs,tp.d-p[u].v+p[rs].v));int t = p[u].tl;if(rt[t])q.push(Pair(rt[t],p[rt[t]].v+tp.d));}printf("%d\n",ans);return 0;
}
View Code

 

转载于:https://www.cnblogs.com/LiGuanlin1124/p/10295222.html

这篇关于SDOI2010 魔法猪学院的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/441023

相关文章

探索Python的数学魔法:Numpy库的神秘力量

文章目录 探索Python的数学魔法:Numpy库的神秘力量背景:为什么选择Numpy?Numpy是什么?如何安装Numpy?五个简单的库函数使用方法场景应用常见Bug及解决方案总结 探索Python的数学魔法:Numpy库的神秘力量 背景:为什么选择Numpy? 在Python的世界中,数据处理和科学计算是不可或缺的一部分。但原生Python在处理大规模数据时可能会显

玩转Python Turtle库,实现满屏飘字的魔法!

前言     本文将教你如何使用Python的Turtle库,通过简单的编程实现满屏飘字的炫酷效果。无需复杂的编程知识,跟着我们的步骤,你也可以成为编程小达人! 效果展示 开发过程 一、准备工作 首先,确保你的电脑上已经安装了Python环境。然后,你需要安装或更新Turtle库(通常Python安装时自带了Turtle库)。 二、编写代码 接下来,我们将通过编写一个简单的P

重复采样魔法:用更多样本击败单次尝试的最强模型

这篇文章探讨了通过增加生成样本的数量来扩展大型语言模型(LLMs)在推理任务中的表现。 研究发现,重复采样可以显著提高模型的覆盖率,特别是在具有自动验证工具的任务中。研究还发现,覆盖率与样本数量之间的关系可以用指数幂律建模,揭示了推理时间的扩展规律。尽管多数投票和奖励模型在样本数量增加时趋于饱和,但在没有自动验证工具的任务中,识别正确样本仍然是一个重要的研究方向。 总体而言,重复采样提供了一种

奇舞学院JS02—JS概览

0、过程抽象已有API实例 利用高阶函数去反参,进而实现参数的“翻转”。 // 已有API函数function setColor(color, el) {el.style.color = color;}// setColor('red', content);function reverseArgs(fn){return function(...args){args = args.rever

奇舞学院JS01—如何写好原生JS

1、交通灯实例 <!DOCTYPE html><html><head><title>js04-1</title><meta charset="utf-8"><link rel="stylesheet" type="text/css" href="js04-1.css"><script type="text/javascript" src="js04-1.js"></script></hea

07_TensorFlow2图像编解码大揭秘:让图片说‘变’就‘变’,魔法还是科技?

1. 图像的编码和解码 在实际应用中,图像数据源格式多种多样,如:png\jpg\bmp等,而神经网络训练模型所需的图像的数据格式为:图像字节数据或Base64编码数据等。基于此,将png\jpg\bmp等格式的图像转换为字节数据的过程称为图像编码,将字节数据的图像转换为png\jpg\bmp等格式图像的过程称为图像解码。 2. 图像编码 Tensorflow图像编码的过程如下图所示,分

【Jupyter】 Notebook 中的 IPython 魔法:12个必知实用技巧

Jupyter Notebook 作为一个强大的交互式计算环境,结合 IPython 的功能,为数据科学家和程序员提供了丰富的工具。本文将介绍12个在 Jupyter Notebook 中使用 IPython 的实用技巧 1. 清除输出:使用 clear_output() from IPython.display import clear_output# 执行一些操作print("This

天津大学仁爱学院教务网、图书馆以及数字化平台网址

天津大学仁爱学院教务网:http://jw.tjrac.edu.cn/ 天津大学仁爱学院数字化平台:http://jw.tjrac.edu.cn/bm 天津大学仁爱学院图书馆: http://121.193.129.2:8080/opac/search.php

【深度学习 激活函数】激活函数:深度学习界的“魔法药剂”

大家好!今天我们来聊聊深度学习中的一个重要角色——激活函数。你是否曾经好奇过,为什么神经网络能像魔法一样识别图片、理解和生成文字?答案就在于这些神奇的激活函数! 激活函数:神经网络的“心跳” 想象一下,神经网络就像一个巨大的生物体,而激活函数就是它的心跳。没有心跳,生物体就无法生存;同样,没有激活函数,神经网络就无法正常工作。 激活函数的“魔法” 激活函数就像是给神经网络施加了魔法,让它们

【C#编程技术总结】魔法包唤醒同一局域网设备

目录 一、原理 Wake-on-LAN (WOL) 的工作原理 典型应用场景 配置要求 注意事项 二、代码 一、原理 魔术包(Magic Packet)是Wake-on-LAN(WOL)技术的一部分,它允许远程唤醒网络设备,如计算机或服务器。这个功能通常用于节能和远程管理,当设备处于待机或休眠状态时,可以通过网络将其唤醒,而无需物理操作。 Wake-on-LAN (WOL