bzoj 2763: [JLOI2011]飞行路线
/* 这做法好像有个很高大上的名字叫做分层图. 其实就是按照题目的意思重新建图 节点有n个变成n*k个 每个表示节点的编号和剩下能用的k值 然后...卡spfa 需要堆优化的dij */ #include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<vector> #define pa pair<int,int> #define mk make_pair #define maxn 2000010 using namespace std; int n,m,k,s,t,num,head[maxn],dis[maxn],c[maxn]; int x[maxn],y[maxn],z[maxn],ans=0xfffffff; priority_queue<pa,vector<pa>,greater<pa> >q; bool f[maxn]; struct node { int u,v,pre,t; }e[maxn]; void Add(int from,int to,int Dis) { for(int i=head[from];i;i=e[i].pre) if(e[i].v==to) { e[i].t=min(e[i].t,Dis); return; } num++; e[num].u=from; e[num].v=to; e[num].t=Dis; e[num].pre=head[from]; head[from]=num; } void Dij(int x) { memset(dis,127/3,sizeof(dis)); dis[x]=0;q.push(mk(0,x)); while(!q.empty()) { int d=q.top().first; int k=q.top().second;q.pop(); if(f[k])continue;f[k]=1; for(int i=head[k];i;i=e[i].pre) { int v=e[i].v; if(dis[v]>dis[k]+e[i].t) { dis[v]=dis[k]+e[i].t; q.push(mk(dis[v],v)); } } } } int main() { scanf("%d%d%d%d%d",&n,&m,&k,&s,&t); s++;t++;n=n+n*k; for(int i=1;i<=m;i++) scanf("%d%d%d",&x[i],&y[i],&z[i]),x[i]++,y[i]++; for(int i=1;i<=m;i++) for(int j=1;j<=k+1;j++) { Add((x[i]-1)*(k+1)+j,(y[i]-1)*(k+1)+j,z[i]); Add((y[i]-1)*(k+1)+j,(x[i]-1)*(k+1)+j,z[i]); if(j<=k) { Add((x[i]-1)*(k+1)+j,(y[i]-1)*(k+1)+j+1,0); Add((y[i]-1)*(k+1)+j,(x[i]-1)*(k+1)+j+1,0); } } Dij((s-1)*(k+1)+1); for(int j=1;j<=k+1;j++) ans=min(ans,dis[(t-1)*(k+1)+j]); printf("%d\n",ans); return 0; }