bzoj2662 [BeiJing wc2012]冻结
Description
“我要成为膜法少女!”
“那么,以灵魂为代价,你希望得到什么?”
“我要将有关膜法和奇迹的一切,封印于卡片之中„„”
在这个愿望被实现以后的世界里,人们享受着膜法卡片(SpellCard,又名符卡)带来的便捷。
现在,不需要续上1s也可以使用膜法了!你还不来试一试?
比如,我们在膜法百科全书(Encyclopedia of Jiang)里用“ excited ”作为关键字来查询,会有很多有趣的结果。
例如,我们熟知的Cirno,她的冰冻膜法当然会有对应的 SpellCard 了。 当然,更加令人惊讶的是,居然有续命的魔法,Cirno 的冻蛤比起这些来真是小巫见大巫了。
这说明之前的世界中有很多魔法少女曾许下控制时间的愿望,比如 Akemi Homura、Sakuya Izayoi、„„
当然,在本题中我们并不是要来研究历史的进程的,而是研究膜法的应用。
我们考虑最简单的旅行问题吧: 现在这个大陆上有 \(N\) 个城市,\(M\) 条双向的道路。城市编号为 \(1\)~\(N\),我们在 \(1\) 号城市,需要到 \(N\) 号城市,怎样才能最快地到达呢?
这不就是最短路问题吗?我们都知道可以用 Dijkstra、Bellman-Ford、Floyd-Warshall等算法来解决。
现在,我们一共有 \(K\) 张可以续命 \(50\%\) 的 SpellCard,也就是说,在通过某条路径时,我们可以选择使用一张卡片,这样,我们通过这一条道路的生命就可以减少到原先的一半。需要注意的是:
- 在一条道路上最多只能使用一张 SpellCard。
- 使用一张SpellCard 只在一条道路上起作用。
- 你不必使用完所有的 SpellCard。
给定以上的信息,你的任务是:求出在可以使用这不超过 \(K\) 张续命的SpellCard 之情形下,从城市 \(1\) 到城市 \(N\) 最少需要多长时间。
Input
第一行包含三个整数: \(N,M,K\) 。
接下来 \(M\) 行,每行包含三个整数: \(A_i,B_i,Time_i\) ,表示存在一条 \(A_i\) 与 \(B_i\) 之间的双向道路,在不使用 SpellCard 之前提下,通过它需要 \(Time_i\) 的时间。
Output
输出一个整数,表示从 \(1\) 号城市到 \(N\) 号城市的最小用时。
Sample Input
4 4 1
1 2 4
4 2 6
1 3 8
3 4 8
Sample Output
7
HINT
对于 \(100\%\) 的数据: \(1 ≤ K ≤ N ≤ 50,M ≤ 1000\) 。
\(1≤ A_i,B_i ≤ N,2 ≤ Time_i ≤ 2000\) 。
为保证答案为整数,保证所有的 \(Time_i\) 均为偶数。
所有数据中的无向图保证无自环、重边,且是连通的
Solution
会做 \(2763\) 吗?
#include<bits/stdc++.h>
using namespace std;
#define N 101
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define fech(i, x) for (int i = 0; i < x.size(); i++)
#define ll long long
inline int read() {
int x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
}
int n, m, k;
struct edge { int u, v, w; } eg[2001]; int tot;
vector<int> g[N];
int d[N][101];
bool vis[N][101];
struct node {
int u, d, f;
bool operator < (const node& b) const { return d > b.d; }
};
priority_queue<node> q;
void bfs() {
memset(d, 127, sizeof d); d[1][0] = 0;
q.push(node { 1, 0, 0 });
while(!q.empty()) {
node x = q.top(); q.pop();
int u = x.u, dis = x.d, f = x.f;
if(!(u ^ n)) { cout << dis; exit(0); }
if(vis[u][f]) continue;
vis[u][f] = 1;
fech(i, g[u]) {
edge e = eg[g[u][i]];
if(f < k && !vis[e.v][f + 1] && d[e.v][f + 1] > dis + (e.w >> 1)) d[e.v][f + 1] = dis + (e.w >> 1), q.push(node{ e.v, d[e.v][f + 1], f + 1 });
if(!vis[e.v][f] && d[e.v][f] > dis + e.w) d[e.v][f] = dis + e.w, q.push(node{ e.v, dis + e.w, f });
}
}
}
int main() {
scanf("%d%d%d", &n, &m, &k);
while(m--) {
int u = read(), v = read(), w = read();
eg[++tot] = edge { u, v, w }; g[u].push_back(tot);
eg[++tot] = edge { v, u, w }; g[v].push_back(tot);
}
bfs();
}