
BZOJ_1916_[Usaco2010 Open]冲浪_分层图+拓扑排序+DP
9
由于K很小,可以像分层图那样设状态,F[i][j]表示从i到n,使用j次改变的最短路。
分两步转移,是否使用改变,如果使用则找一个最小的转移,否则找一个最长的。
然后这个建反图拓扑排序即可。
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 50050 #define M 150050 typedef long long ll; ll f[N][11],mn[N][11],mx[N][11]; int head[N],to[M],nxt[M],cnt,val[M],Q[N],l,r,in[N],n,m,K; inline void add(int u,int v,int w) { to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w; } int main() { scanf("%d%d%d",&n,&m,&K); int i,x,y,z,j; for(i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); add(y,x,z); in[x]++; } for(i=0;i<=K;i++) f[n][i]=0; memset(mn,0x3f,sizeof(mn)); Q[r++]=n; while(l<r) { x=Q[l++]; for(i=0;i<=K;i++) f[x][i]=min(mx[x][i],mn[x][i]); for(i=head[x];i;i=nxt[i]) { for(j=0;j<=K;j++) mx[to[i]][j]=max(mx[to[i]][j],f[x][j]+val[i]); for(j=0;j<K;j++) mn[to[i]][j]=min(mn[to[i]][j],f[x][j+1]+val[i]); if((--in[to[i]])==0) Q[r++]=to[i]; } } printf("%lld\n",f[1][0]); }
BZOJ_1916_[Usaco2010 Open]冲浪_分层图+拓扑排序+DP
原文:https://www.cnblogs.com/suika/p/9215459.html