UVA10269 最短路

来源:互联网 发布:d800微调优化曝光 编辑:程序博客网 时间:2024/05/16 09:52

题意:给定A个村庄和B个城堡,村庄编号为1到A,城堡编号为A+1到A+B,求问点1到点A+B最短路。其中可以开挂k次,每次可以瞬移最大距离为L。但有一个限制条件,瞬移经过的路径只能包含村庄。


分析:先用floyd求出任意两点只经过村庄的最短路。然后用SPFA求出点1到点A+B的最短路。类似求解动规,定义 d[u][k] 表示 从起点到点u 使用k次魔法所花费的最短时间。


代码如下:

#include <cstdio>#include <cstring>#include <queue>using namespace std;const int maxk = 15;const int INF = 1e9;const int maxn = 100+10;int A,B,m,L,k,n;int a[maxn][maxn],d[maxn][maxk],vis[maxn][maxk];void init(){   scanf("%d %d %d %d %d",&A,&B,&m,&L,&k);   n = A+B;   for (int i=1; i<=n; i++) {      for (int j = 1; j<=n ; j++ ) a[i][j] = INF;      a[i][i] = 0;   }}inline int Min(int x, int y) { return x<y?x:y; }inline int Max(int x, int y) { return x>y?x:y; }void floyd(){    for (int k=1; k<=A; k++) {        for (int i=1; i<=n; i++) {            for (int j=1; j<=n; j++) {                if (k==i || k==j) continue;                a[i][j] = Min(a[i][j],a[i][k]+a[k][j]);            }        }    }}queue <int>que,times;void SPFA(){   for (int i=1; i<=n; i++)     for (int j=0; j<=k; j++) d[i][j] = INF;   for (int i=0; i<=k; i++) d[1][i] = 0;   memset(vis,0,sizeof(vis));   while (!que.empty()) que.pop(); que.push(1);   while (!times.empty()) times.pop(); times.push(0);   int u,v;   while (!que.empty()){       u = que.front(); que.pop();       v = times.front(); times.pop();       vis[u][v] = 0;       for (int i=1; i<=n; i++) {           if ( u == i) continue;           if ( d[i][v] > d[u][v] + a[u][i]) {               d[i][v] = d[u][v] + a[u][i];               if (!vis[i][v]) {                   que.push(i);                   times.push(v);                   vis[i][v] = 1;               }           }           if (a[u][i] <= L && v<k && d[i][v+1]>d[u][v]){                d[i][v+1] = d[u][v];                if (!vis[i][v+1]){                    que.push(i);                    times.push(v+1);                    vis[i][v+1] = 1;                }           }       }   }}int main(){    int T;    scanf("%d",&T);    while (T--){        init();        int u,v,w;        for (int i=1; i<=m; i++) {            scanf("%d %d %d",&u,&v,&w);            a[u][v] = a[v][u] = w;        }        floyd();        SPFA();        int ans = INF;        for (int i=0; i<=k; i++) ans = Min(ans,d[n][i]);        printf("%d\n",ans);    }    return 0;}


原创粉丝点击