分层图
分层图是针对于对图的边权有强制性修改的一类问题(修改次数较少);
它的思想其实就是拆点。
以上面这道题为例:
将k条边的权值变为0;
将原图建为k层每一个层内之间的边权不变,跨层的边权设为0;
这样就实现了分层图;
再在分层图上跑一边最短路就可以了;
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100100 ;
const int maxm = 500001 ;
int n,m,k,head[maxn*22],cnt=0,dis[maxn*22];
priority_queue < pair <int ,int > > q ;
struct edge
{
int to,pre,val;
}e[maxm*2*20];
inline void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9') {if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
inline void add(int x,int y,int z)
{
e[++cnt].pre=head[x];
e[cnt].to=y;
e[cnt].val=z;
head[x]=cnt;
}
void DJ()
{
memset(dis,0x3f,sizeof(dis));
dis[1]=0;
q.push(make_pair(0,1));
while(q.size())
{
int x=q.top().second;
q.pop();
for(int i=head[x];i;i=e[i].pre)
{
int y=e[i].to;
int z=e[i].val;
if(dis[x]+z<dis[y])
{
dis[y]=dis[x]+z;
q.push(make_pair(-dis[y],y));
}
}
}
}
int main()
{
//freopen("testdata.in","r",stdin);
read(n);read(m);read(k);
for(int i=1;i<=m;++i)
{
int x,y,z;
read(x);read(y);read(z);
add(x,y,z);
add(y,x,z);
for(int j=1;j<=k;++j)
{
add(j*n+x,j*n+y,z);
add(j*n+y,j*n+x,z);
add((j-1)*n+x,j*n+y,0);
add((j-1)*n+y,j*n+x,0);
}
}
DJ();
int ans=dis[n];
for(int i=1;i<=k;++i)
ans=min(ans,dis[i*n+n]);
printf("%d",ans);
return 0;
}