Description
异变又发生了,魂魄妖梦作为幻想乡的一名自(cheng)机(guan),主动前去解决异变。
我们用一个n个点、m条边的无向联通图来表示妖梦可选择的路线,妖梦从白玉楼出发,白玉楼被视为编号为1的点,编号为2——n的点是幻想乡的村庄,其中编号为n的村庄发生了异变。
每条边上可能会有一些妖怪袭击人类(然而妖梦是半人半灵),所以对于第i条边,妖梦需要t[i]分钟通过这条路。妖梦带了她的人符[现世斩],可以使所有连接点x的边的通过时间变成1(x可以任意指定)。然而为了保留足够的力量解决异变,妖梦只会用这个符卡一次。妖梦想知道,她到达村庄n的最短时间是多少。
Solution
显然把原图分成三层,跑一次最短路即可。
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define N 300001
#define M 4000001
#define ll long long
using namespace std;
int to[M],next[M],last[M],val[M],num=0;
void link(int x,int y,int c)
{
num++;
to[num]=y;
next[num]=last[x];
last[x]=num;
val[num]=c;
}
int d[M];
ll dis[N];
bool vis[N];
void spfa(int s)
{
memset(dis,60,sizeof(dis));
dis[1]=0;
vis[1]=true;
d[1]=1;
int l=0,r=1;
while(l<r)
{
int x=d[++l];
for(int i=last[x];i;i=next[i])
{
int v=to[i];
if(dis[x]+val[i]<dis[v])
{
dis[v]=dis[x]+val[i];
if(!vis[v])
{
vis[v]=true;
d[++r]=v;
}
}
}
vis[x]=false;
}
}
int main()
{
freopen("cut.in","r",stdin);
freopen("cut.out","w",stdout);
int n,m;
cin>>n>>m;
fo(i,1,m)
{
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
if(u!=v)
{
link(u,v,w);
link(v,u,w);
link(u,v+n,1);
link(u+n,v+n*2,1);
link(v,u+n,1);
link(v+n,u+n*2,1);
link(u+n*2,v+n*2,w);
link(v+n*2,u+n*2,w);
}
}
spfa(1);
cout<<dis[n*3];
}
幻想乡异变最短路径

本文介绍了一个基于最短路径算法的游戏场景问题解决方法。在一个由n个节点和m条边组成的无向图中,通过特殊的符卡能力,寻找从起点到发生异变的村庄的最短时间路径。
945

被折叠的 条评论
为什么被折叠?



