分层图+堆优化的题
分层图,顾名思义就是将图分层,每一层代表一个不同状态。如本题中的一层就代表修建一次高速公路(或说将一条路免费),连接每一层图的则是边权为0的单向边。
因为我们并不需要将修建高速公路的机会使用完,所以最终答案应从每一层的节点N中找。
为了不T掉,我们要用堆优化降低复杂度。
因此思路如下:
- 根据题意建立k+1层,每层n个节点的分层图;
- 堆优化DIJ遍历;
- 在每一层的节点n中取最小值作为答案输出。
code:
#include<bits/stdc++.h>
using namespace std;
int n,m,k,s,t,w[100100],fst[100100],nex[100100],v[100100],dis[32][10100],a,b,c,tot,vis[32][10100];
struct item
{
int lev,d,x;
bool operator< (const item &x) const
{
return d>x.d;
}
};
priority_queue<item>q;
void add(int a,int b,int c)
{
nex[++tot]=fst[a];
w[tot]=c;
v[tot]=b;
fst[a]=tot;
return ;
}
void dij()
{
dis[0][s]=0;
q.push((item){0,0,s});
while(!q.empty())
{
int x=q.top().x,d=q.top().d,lev=q.top().lev;
//cout<<lev<<" "<<x<<" "<<d<<" "<<vis[lev][x]<<endl;
//system("pause");
q.pop();
if(vis[lev][x])
continue;
vis[lev][x]=1;
for(int i=fst[x];i!=-1;i=nex[i])
{
if(!vis[lev][v[i]]&&d+w[i]<dis[lev][v[i]])
{
dis[lev][v[i]]=d+w[i];
q.push((item){lev,d+w[i],v[i]});
}
if(!vis[lev+1][v[i]]&&d<dis[lev+1][v[i]]&&lev+1<=k)
{
dis[lev+1][v[i]]=d;
q.push((item){lev+1,d,v[i]});
}
}
}
return ;
}
int main()
{
memset(fst,-1,sizeof(fst));
memset(dis,0x7f/3,sizeof(dis));
cin>>n>>m>>k;
s=1;t=n;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
dij();
int ans=1e8;
for(int i=0;i<=k;i++)
{
ans=min(ans,dis[i][t]);
}
cout<<ans;
return 0;
}