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
****************************************************************/