您的位置:首页 > 其它

【JZOJ4597】现世斩

2016-07-18 09:59 232 查看

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
;
bool vis
;
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];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: