1225: 最小花费
Description
现在给出N个城市,城市之间共有M条道路。道路表示的方法是<u,v,w>,
代表从编号为u的城市,到标号为v的城市有条花费为w的道路。
现在我们从编号为S的城市出发,目的地是编号为T的城市。
但是我们在旅途中从u号城市到v号城市花费不只是他们的道路的花费w,
还要加上以前的所有花费的一半,向下取整。
Input
第一行一个正整数T<=10,代表测试数据个数
对每组测试数据:
第一行两个正整数N,M代表城市的个数,和道路的个数
2<=N<=1000
0<=M<=100000
然后给出M行,每行三个正整数u,v,w代表每条道路的信息,道路都是双向的
u,v,w代表从编号为u的城市,到编号为v的城市有一条花费为w的道路
城市的编号是从1到N的,w的范围是[1,10000]
最后一行是两个正整数S,T代表出发地和目的地
Output
如果不存在从S到T的路径输出-1,否则输出最小花费,每组测试数据的输出占一行
Sample Input
2
3 2
1 2 3
2 3 4
1 3
2 0
1 2
Sample Output
8
-1
HINT
从1到2,花费3+0/2=3
从2到3,花费4+3/2=5
总花费为8
输入数据较大,不要用cin读入数据
乍一看以为是最短路,仔细一看“但是我们在旅途中从u号城市到v号城市花费不只是他们的道路的花费w,还要加上以前的所有花费的一半,向下取整。”这怎么能是最短路嘞~
后来问了别人,好吧,还是最短路。
自己学的太死了。
只是把最短路更新的语句改了一下,基本没动。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int MAX = 1005; const int INF = 0x7ffffff; int mp[MAX][MAX]; int vis[MAX]; int dis[MAX]; int dij(int n, int s, int e) { int m; int k; memset(vis, 0, sizeof(vis)); for (int i = 0; i < n; i++) { dis[i] = mp[s][i]; } vis[s] = 1; for (int i = 1; i < n; i++) { m = INF; k = 1; for (int j = 0; j < n; j++) { if (!vis[j] && m > dis[j]) { m = dis[j]; k = j; } } vis[k] = 1; if (k == e) return m; for (int j = 0; j < n; j++) { //只有这里需要改动一下 if (!vis[j] && dis[j] > dis[k] + dis[k] / 2 + mp[k][j]) { dis[j] = dis[k] + dis[k] / 2 + mp[k][j]; } } } return dis[e]; } int main() { int t; int m, n; int a, b, c; int s, e; scanf("%d", &t); while (t--) { scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i == j) mp[i][j] = 0; else mp[i][j] = INF; } } for (int i = 0; i < m; i++) { scanf("%d%d%d", &a, &b, &c); if (mp[a - 1][b - 1] > c) mp[a - 1][b - 1] = mp[b - 1][a - 1] = c; } scanf("%d%d", &s, &e); int ans = dij(n, s - 1, e - 1); if (ans == INF) ans = -1; printf("%d\n", ans); } return 0; } /************************************************************** Problem: 1225 User: Language: C++ Result: Accepted Time:972 ms Memory:5600 kb ****************************************************************/