显而易见的 dp 方程,dp [ x ] [ i ] 表示到达点 x 免费了 i 条边的最短时间。
dp [ x ] [ i ] = min ( dp [ pre ] [ i - 1 ] , dp [ pre ] [ i ] + dis [ pre ] [ x ] ) ;
如果直接跑dp,得搞个拓扑图,并且环上信息不会统计。
考虑分层图,然后就是一个分层图模板了。
(回家画个图)
1 #include<cstdio> 2 #include<string> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 #define int long long 7 using namespace std; 8 int read(){ 9 int x;scanf("%lld",&x);return x; 10 } 11 12 const int N=220005; 13 14 int n,m,k; 15 int p1,p2,t; 16 17 struct node{ 18 int y,z,nxt; 19 }e[N*20]; 20 int tot=0,h[N]; 21 void ad(int x,int y,int z){ 22 ++tot;e[tot].y=y;e[tot].z=z;e[tot].nxt=h[x];h[x]=tot; 23 } 24 25 int dis[N],vis[N]; 26 priority_queue< pair<int,int> > q; 27 void dij(){ 28 29 q.push(make_pair(0,1)); 30 while(!q.empty()){ 31 int x=q.top().second;q.pop(); 32 if(vis[x])continue; 33 vis[x]=1; 34 for(int i=h[x];i;i=e[i].nxt){ 35 int y=e[i].y; 36 if(dis[y]>dis[x]+e[i].z){ 37 dis[y]=dis[x]+e[i].z; 38 q.push(make_pair(-dis[y],y)); 39 } 40 } 41 } 42 } 43 44 signed main(){ 45 n=read();m=read();k=read(); 46 while(m--){ 47 p1=read();p2=read();t=read(); 48 ad(p1,p2,t);ad(p2,p1,t); 49 for(int j=1;j<=k;++j){ 50 ad(p1+j*n,p2+j*n,t);ad(p2+j*n,p1+j*n,t); 51 ad(n*(j-1)+p1,n*j+p2,0);ad(n*(j-1)+p2,n*j+p1,0); 52 } 53 } 54 memset(dis,0x3f,sizeof(dis)); 55 memset(vis,0,sizeof(vis)); 56 dis[1]=0; 57 dij(); 58 int ans=dis[n]; 59 for(int i=1;i<=k;++i){ 60 ans=min(ans,dis[n*i+n]); 61 } 62 printf("%lld",ans); 63 }
zpj直接yy出分层图,tql。
原文地址:https://www.cnblogs.com/chiyo/p/11434243.html
时间: 2024-10-10 19:01:52