【洛谷P4568】[JLOI2011]飞行路线
飞行路线
今天上午模拟考试考了原题,然而数组开小了,爆了4个点。
据王♂强dalao说这是一道分层图SPFA的裸题
dis[i][j]表示到点i用k个医疗包的最小消耗,dis[u][j]+e[i].w更新dis[v][j],
dis[u][j]更新dis[v][j+1]
然而它卡SPFA,会TLE几个点
于是就有了堆优化SPFA。。(它就是堆优化dijkstra。。)
#include<cstring> #include<cstdio> #include<queue> #define INF 0x3f3f3f3f #define N 10010 int n,m,k,s,t,ans=INF; int dis[N][12]; struct HA{ int pos,cost,times; }; struct cmp{ bool operator()(HA x,HA y){ return x.cost==y.cost?x.times>y.times:x.cost>y.cost; } }; std::priority_queue< HA, std::vector<HA>, cmp > q; bool vis[N][12]; int Head[N],num; struct NODE{ int to,w,next; } e[100010]; const int ch_top=4e7+3; char ch[ch_top],*now_r=ch-1,*now_w=ch-1; inline int read(){ while(*++now_r<'0'); register int x=*now_r-'0'; while(*++now_r>='0')x=x*10+*now_r-'0'; return x; } inline void write(int x){ static char st[20];static int top; while(st[++top]='0'+x%10,x/=10); while(*++now_w=st[top],--top); *++now_w='\n'; } void SPFA(){ memset(dis,0x3f,sizeof(dis)); for(int i=0;i<=k;i++){ dis[s][i]=0; q.push((HA){s,0,i}); } while(!q.empty()){ int u=q.top().pos,f=q.top().times; q.pop(); vis[u][f]=0; for(int i=Head[u];i;i=e[i].next){ int v=e[i].to; if(dis[v][f]>dis[u][f]+e[i].w){ dis[v][f]=dis[u][f]+e[i].w; if(!vis[v][f]){ vis[v][f]=1; q.push(HA{v,dis[v][f],f}); } } if(f<k&&dis[v][f+1]>dis[u][f]){ dis[v][f+1]=dis[u][f]; if(!vis[v][f+1]){ vis[v][f+1]=1; q.push(HA{v,dis[v][f+1],f+1}); } } } } } int main() { fread(ch,1,ch_top,stdin); n=read(); m=read(); k=read(); s=read(); t=read(); int x,y,w; for(int i=1;i<=m;i++){ x=read(); y=read(); w=read(); e[++num].to=y; e[num].w=w; e[num].next=Head[x]; Head[x]=num; e[++num].to=x; e[num].w=w; e[num].next=Head[y]; Head[y]=num; } SPFA(); write(dis[t][k]); fwrite(ch,1,now_w-ch,stdout); return 0; }