bzoj2662 [BeiJing wc2012]冻结

21 篇文章 0 订阅
5 篇文章 0 订阅
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 行,每行包含三个整数: Ai,Bi,Timei ,表示存在一条 Ai Bi 之间的双向道路,在不使用 SpellCard 之前提下,通过它需要 Timei 的时间。

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% 的数据: 1KN50,M1000
1AiBiN,2Timei2000
为保证答案为整数,保证所有的 Timei 均为偶数。
所有数据中的无向图保证无自环、重边,且是连通的

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();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值