【问题描述】
Vasya在玩一个叫做"Dwarf Tower"的游戏,这个游戏中有n个不同的物品,
它们的编号为1到n。现在Vasya想得到编号为1的物品。
获得一个物品有两种方式:
1. 直接购买该物品,第i件物品花费的钱为ci
2. 用两件其他物品合成所需的物品,一共有m种合成方式。
请帮助Vasya用最少的钱获得编号为1的物品。
【输入格式】
第一行有两个整数n,m(1<=n<=10000,0<=m<=100000),分别表示有n种物品以
及m种合成方式。
接下来一行有n个整数,第i个整数ci表示第i个物品的购买价格,其中
0<=ci<=10^9。
接下来m行,每行3个整数ai,xi,yi,表示用物品xi和yi可以合成物品ai,其
中(1<=ai,xi,yi<=n; ai<>xi, xi<>yi, yi<>ai)
【输出格式】
一行,一个整数表示获取物品 1 的最少花费。
输入样例: | 输出样例: |
5 3 5 0 1 2 5 5 2 3 4 2 3 1 4 5 |
2 |
【数据规模与约定】
60%的数据, n<=100
100%的数据, n<=10000, m<=100000
分析:稍微想一想就能发现这是最短路,合成操作看成松弛操作就可以了.
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int inf = 0x7fffffff; int n, m, c[10010], d[10010],head[10010], to[200010], nextt[200010], w[200010], tot = 1; bool vis[10010]; void add(int x, int y, int z) { w[tot] = z; to[tot] = y; nextt[tot] = head[x]; head[x] = tot++; } void spfa() { queue <int> q; for (int i = 1; i <= n; i++) { d[i] = c[i]; vis[i] = 1; q.push(i); } while (!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; for (int i = head[u]; i; i = nextt[i]) { int v = to[i]; if (d[v] > d[u] + d[w[i]]) { d[v] = d[u] + d[w[i]]; if (!vis[v]) { vis[v] = 1; q.push(v); } } } } } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &c[i]); for (int i = 1; i <= m; i++) { int t, x, y; scanf("%d%d%d", &t, &x, &y); add(x, t, y); add(y, t, x); } spfa(); printf("%d ", d[1]); return 0; }