立刻出行杯-高年级组 F-Stein's Gate(最短路)

立刻出行杯-高年级组 F-Stein's Gate(最短路)_第1张图片

立刻出行杯-高年级组 F-Stein's Gate(最短路)_第2张图片

立刻出行杯-高年级组 F-Stein's Gate(最短路)_第3张图片

思路来源

凯爷

题解

出题人题解

立刻出行杯-高年级组 F-Stein's Gate(最短路)_第4张图片

心得

具体实现的时候,建边要比n建的大一些,要考虑回来情况的最短路,

考虑到最后1e6输出42,那么建边的时候,

最少要建1e6+42叭……其实我最后建的1e6+1e5

建这7条边的确是因为,自己敲了一发bfs,发现100以内的只有10步左右,

所以没必要去扩那么大步,小步小步走比较优,

这就像质数分解一样……能用2去凑反素数,绝不用大素数去凑,

为的是因子个数最多,这里为的是和最小,其实质,差的不是很多。

最小值问题,bfs能解决的,建图最短路一定能解决,爆内存的时候长点心吧。

bfs和最短路之间的互相转化,要多做才有感觉。

凯爷的最短路,还真的是毒瘤呢。

据说记忆化搜索可以做,但我还是赛中WA了4发。

代码

#include 
#include  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
const int INF=0x3f3f3f3f;
const int maxn=1e6+1e5+5;
const int maxm=8e6+10; 
const int mod=1e9+7;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector 
#define si set
#define pli pair 
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a)) 
using namespace std;
int cnt,n,head[maxn];
ll dis[maxn];
bool vis[maxn];
struct edge
{
 int to,nex;ll w;
}e[maxm];
void init(int n)
{
	cnt=0;
	mem(head,-1); 
	mem(vis,0);
	fill(dis,dis+maxn,8e18);
}
void add(int u,int v,ll w)
{
	e[cnt].w=w;
	e[cnt].to=v;
	e[cnt].nex=head[u];
	head[u]=cnt++;
}
priority_queue,greater >q; 
void dijkstra(int s)
{
	q.push(pli(0,s));
	dis[s]=0;
	while(!q.empty())
	{
		pli tmp=q.top();
		q.pop();
		int u=tmp.second;
		if(vis[u])continue;
		vis[u]=1;
		for(int i=head[u];~i;i=e[i].nex)
		{
			int v=e[i].to;
			ll w=e[i].w;
			if(dis[v]>dis[u]+w)
			{
				dis[v]=dis[u]+w;
				q.push(pli(dis[v],v));
			}
		}
	}
}
int main()
{
	scanf("%d",&n);
	init(n);
	for(int i=1;i<=n+1e5;++i)
	{
		if(i-1>=1)add(i,i-1,1);
		if(2*i<=maxn)add(i,2*i,2);
		if(3*i<=maxn)add(i,3*i,3);
		if(5*i<=maxn)add(i,5*i,5);
		if(7*i<=maxn)add(i,7*i,7);
		if(11*i<=maxn)add(i,11*i,11);
		if(13*i<=maxn)add(i,13*i,13);
	}
	dijkstra(1);
	printf("%lld\n",dis[n]);
	return 0;
}

 

你可能感兴趣的:(最短路)