正题
[USACO09FEB]改造路Revamping Trails
”Dp吧“
题意十分简洁,就是求一个有向图去除k条边的权值后的最短路。
我们很容易就想到了一种分层图的做法(就是暴力)。
分层图只是将Dp的思路图像化罢了。
d[x][p]表示x点之前,一共改造p条道路的最小费用。
那么d[x][p]就可以拓展出 d[y][p]+s[i].c 和 d[y][p+1] 两种状态。
所以我们就可以做出这道题。
明显地,边数很多,不能用SPFA做,只能用Dijkstra。
#include<cstdio> #include<cstdlib> #include<cstring> #include<queue> using namespace std; int n,m,k; int len=0; struct edge{ int x,p1,y,p2,next,c; }s[1000010]; struct node{ int x,p; long long d; bool operator<(const node y)const{ return d>y.d; } }; int first[10010]; bool tf[10010][21]; priority_queue<node> f; long long d[10010][21]; void ins(int x,int y,int c){ len++; s[len].y=y;s[len].c=c;s[len].next=first[x];first[x]=len; } int main(){ scanf("%d %d %d",&n,&m,&k); for(int i=1;i<=m;i++){ int x,y,c; scanf("%d %d %d",&x,&y,&c); ins(x,y,c);ins(y,x,c); } memset(d,63,sizeof(d)); d[1][0]=0; f.push((node){1,0,0}); while(!f.empty()){ node x=f.top(); f.pop(); if(tf[x.x][x.p]) continue; tf[x.x][x.p]=true; for(int i=first[x.x];i!=0;i=s[i].next){ int y=s[i].y; if(d[y][x.p+1]>d[x.x][x.p] && x.p+1<=k) { d[y][x.p+1]=d[x.x][x.p]; f.push((node){y,x.p+1,d[y][x.p+1]}); } if(d[y][x.p]>d[x.x][x.p]+s[i].c){ d[y][x.p]=d[x.x][x.p]+s[i].c; f.push((node){y,x.p,d[y][x.p]}); } } } printf("%lld",d[n][k]); }