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();
}
posted @ 2018-02-05 10:15  aziint  阅读(100)  评论(0编辑  收藏  举报
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.