uva 10269(最短路径)

来源:互联网 发布:java 命令行打包 编辑:程序博客网 时间:2024/06/16 05:46

题意:有n个村庄和m个城堡,村庄编号从1开始,城堡编号从n+1开始,一个人带着公主要从城堡n+m到村庄1,他还有一个魔法鞋可以有cnt次的使用机会可以让人能不花费时间走最多l,人只能在路上没有城堡的时候使用这个魔法鞋,问最少花费多少时间能到达村庄1。

题解:最短路径问题,用spfa算法,先用floyd将地点i到j的最短距离求出(不经过城堡),然后用f[i][j]表示到达结点i还剩j次穿魔法鞋机会的花费时间,与普通的spfa不同的是加了一个判断:f[u][t1] > f[i][t1-1],意味着从u到i用一次魔法鞋如果可以减短时间就用掉,并且如果不再队列中就加到队尾。

#include <stdio.h>#include <string.h>#include <queue>using namespace std;const int N = 150;const int INF = 0x3f3f3f3f;int f[N][N], g[N][N], vis[N][N];int t, n, m, p, l, cnt;void spfa() {int st = n + m;queue<int> q1;queue<int> q2;memset(vis, 0, sizeof(vis));memset(f, INF, sizeof(f));for (int i = 0; i <= cnt; i++)f[m + n][i] = 0;q1.push(st);q2.push(cnt);while (!q1.empty()) {int u = q1.front();q1.pop();int t1 = q2.front();q2.pop();vis[u][t1] = 0;for (int i = 1; i <= n + m; i++) {if (f[i][t1] > f[u][t1] + g[u][i]) {f[i][t1] = f[u][t1] + g[u][i];if (!vis[i][t1]) {vis[i][t1] = 1;q1.push(i);q2.push(t1);}}if (t1 > 0 && g[u][i] <= l && f[u][t1] < f[i][t1 - 1]) {f[i][t1 - 1] = f[u][t1];if (!vis[i][t1 - 1]) {vis[i][t1 - 1] = 1;q1.push(i);q2.push(t1 - 1);}}}}}void floyd() {for (int k = 1; k <= n; k++)for (int i = 1; i <= n + m; i++)for (int j = 1; j <= n + m; j++)if (g[i][j] > g[i][k] + g[k][j])g[i][j] = g[i][k] + g[k][j];}int main() {scanf("%d", &t);while (t--) {scanf("%d%d%d%d%d", &n, &m, &p, &l, &cnt);memset(g, INF, sizeof(g));int u, v, w;for (int i = 0; i < p; i++) {scanf("%d%d%d", &u, &v, &w);g[u][v] = g[v][u] = w;}floyd();spfa();int minn = INF;for (int i = 0; i <= cnt; i++)if (minn > f[1][i])minn = f[1][i];printf("%d\n", minn);}return 0;}


0 0
原创粉丝点击