背景
\(USACO \) \(2009 \) \(オン2月\) \(T3 \)、\ (Luogu \) \(P2939 / BZOJ1579 \)
問題の意味
所与\(N- \)点、\(M \)の両端縁\(X、Y \) 、パスは、所定の最大ようにしてもよい(K \)は\エッジとなる(0 \)\。探している\(1 \)に\(N- \)最短路長。
ソリューション
図最短テンプレートを層状。
フリーので\(K \)内蔵回、\(K \)層図(すなわちなると仮定すると(0 \)\、よりグラフのエッジの数以上)とすることができます。
注各エッジは、各レベルで再び接続され、その\(X \)より高いレベルに\(Y \)接続\(0 \)側、\(Y \)より高いレベルに\(X \ )でも\(0 \)側。(1 \)\号時\(ダイクストラ\) 、答えは第一のすべての層のある\(N- \)最短パスの最小点。
ディテール
してくださいマップトピック配列咲く大きな十分にチェックするために注意を払うようにしてください。確認してください確認してくださいリミットデータの検証に代入。
コード
\(ビュー\) \(コード\)
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int ret=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
ret=(ret<<1)+(ret<<3)+ch-'0';
ch=getchar();
}
return ret*f;
}
const int inf=0x3f3f3f3f;
int n,m,k,s,t,u,v,w;
int dis[220005],ans=inf;
int num,head[220005];
bool vis[220005];
struct edge
{
int ver,nxt,w;
}e[4100005];
inline void adde(int u,int v,int w)
{
e[++num].ver=v;
e[num].w=w;
e[num].nxt=head[u];
head[u]=num;
}
void dijkstra(int s)
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
priority_queue<pair<int,int> > q;
dis[s]=0;
q.push(make_pair(0,s));
while(!q.empty())
{
int x=q.top().second;
q.pop();
if(vis[x])
continue;
vis[x]=1;
for(register int i=head[x];i;i=e[i].nxt)
{
int y=e[i].ver,w=e[i].w;
if(dis[x]+w<dis[y])
{
dis[y]=dis[x]+w;
q.push(make_pair(-dis[y],y));
}
}
}
}
int main()
{
n=read();
m=read();
k=read();
s=1;
t=n;
for(register int i=1;i<=m;i++)
{
u=read();
v=read();
w=read();
adde(u,v,w);
adde(v,u,w);
for(register int j=1;j<=k;j++)
{
adde(u+(j-1)*n,v+j*n,0);
adde(v+(j-1)*n,u+j*n,0);
adde(u+j*n,v+j*n,w);
adde(v+j*n,u+j*n,w);
}
}
dijkstra(s);
for(register int i=0;i<=k;i++)
ans=min(ans,dis[t+i*n]);
if(ans<inf)
printf("%d\n",ans);
else
printf("-1\n");
return 0;
}