分层图
分层图
分层图的两种写法
P4568 [JLOI2011] 飞行路线
1.建立实际的多层图(直接跑裸的dij就行)
per(i,1,m)
{
scanf("%d%d%d",&x,&y,&po);
++x,++y;
add(x,y,po);
add(y,x,po);
per(j,1,k)
{
add(x+(j-1)*n,y+j*n);
add(y+(j-1)*n,x+j*n);
add(x+j*n,y+j*n,po);
add(y+j*n,x+j*n,po);
}
}
代码:
#include <bits/stdc++.h>
using namespace std;
#define per(i,a,b) for(int i(a);i<=b;++i)
const int N=1e5+1e4+20,M=2500010;
int to[M],hd[N],nx[M],v[M],id;
void add(int x,int y,int c=0)
{
to[++id]=y,nx[id]=hd[x],v[id]=c;
hd[x]=id;
}
int d[N];
bool ck[N];
priority_queue<pair<int,int>>q;
void dij(int x)
{
memset(d,0x3f,sizeof(d));
d[x]=0;
q.emplace(0,x);
while(!q.empty())
{
x=q.top().second,q.pop();
if(ck[x]) continue;
ck[x]=1;
for(int i=hd[x];i;i=nx[i])
{
if(d[to[i]]>d[x]+v[i])
{
d[to[i]]=d[x]+v[i];
q.emplace(-d[to[i]],to[i]);
}
}
}
}
int main()
{
int n,m,k,s,t,x,y,po;
cin>>n>>m>>k>>s>>t;
++s,++t;
per(i,1,m)
{
scanf("%d%d%d",&x,&y,&po);
++x,++y;
add(x,y,po);
add(y,x,po);
per(j,1,k)
{
add(x+(j-1)*n,y+j*n);
add(y+(j-1)*n,x+j*n);
add(x+j*n,y+j*n,po);
add(y+j*n,x+j*n,po);
}
}
per(i,1,k)
{
add(t+(i-1)*n,t+i*n);
}
dij(s);
printf("%d\n",d[t+k*n]);
return 0;
}
2.引入dp思想进行分层松弛(不用建立很多层点)
for(int i=hd[x];i;i=nx[i])
{
if((c<k)&&!ck[to[i]][c+1]&&d[to[i]][c+1]>d[x][c])
{
d[to[i]][c+1]=d[x][c];
q.emplace((aaa){to[i],d[to[i]][c+1],c+1});
}
if(!ck[to[i]][c]&&d[to[i]][c]>d[x][c]+v[i])
{
d[to[i]][c]=d[x][c]+v[i];
q.emplace((aaa){to[i],d[to[i]][c],c});
}
}
代码:
#include <bits/stdc++.h>
using namespace std;
#define per(i,a,b) for(int i(a);i<=b;++i)
const int N=1e4+10,M=1e5+10;
int to[M],nx[M],hd[N],v[M],id;
int n,m,k,s,t;
int d[N][15];
bool ck[N][15];
struct aaa{
int x,po,t;
bool operator <(const aaa e) const{
return po>e.po;
}
}w;
priority_queue<aaa>q;
void add(int x,int y,int po)
{
to[++id]=y,nx[id]=hd[x],v[id]=po;
hd[x]=id;
}
void dij()
{
int x,c;
memset(d,0x3f,sizeof(d));
d[s][0]=0;
q.emplace((aaa){s,0,0});
while(!q.empty())
{
w=q.top(),q.pop();
x=w.x,c=w.t;
// if(ck[x][c]) continue;
ck[x][c]=1;
for(int i=hd[x];i;i=nx[i])
{
if((c<k)&&!ck[to[i]][c+1]&&d[to[i]][c+1]>d[x][c])
{
d[to[i]][c+1]=d[x][c];
q.emplace((aaa){to[i],d[to[i]][c+1],c+1});
}
if(!ck[to[i]][c]&&d[to[i]][c]>d[x][c]+v[i])
{
d[to[i]][c]=d[x][c]+v[i];
q.emplace((aaa){to[i],d[to[i]][c],c});
}
}
}
}
int main()
{
int x,y,po,ans=INT_MAX;
cin>>n>>m>>k>>s>>t;
++s,++t;
per(i,1,m)
{
scanf("%d%d%d",&x,&y,&po);
++x,++y;
add(x,y,po),add(y,x,po);
}
dij();
per(i,0,k)
{
ans=min(ans,d[t][i]);
// printf("%d\n",d[t][i]);
}
printf("%d\n",ans);
return 0;
}