Skip to content

11138: 【原1138】主任是好人

题目

题目描述

author: Wengong Jin 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1138

Description

话说主任在刷题的时候看到了这样一道题:

S国有N个城市,若干城市之间有道路连接,每条道路有一个坚固指数。 现在T国要破坏S国若干条道路,使得城市1和城市N不连通。 但是破坏道路需要费用,破坏所需的费用等于道路的坚固指数。 于是T国的国王找到了你,希望你能帮助他完成这个任务。

主任当然知道这道题怎么做,但是主任对T国国王无礼的要求感到非常气愤。 “怎么可以把别人辛辛苦苦建造起来的道路就这样破坏掉呢!”

于是主任出了这样一道题:

S国有N个城市,若干城市之间有道路连接,每条道路由于比较陈旧,因此通过这条道路需要时间Ti。 现在S国国王和T国国王成为了好伙伴,于是T国为了帮助S国的国民减少他们从城市1到城市N的时间, 决定给S国修缮K条道路,使得这条道路通行时间为0。 从而使得S国的国民从城市1到城市N的时间最短。 于是T国的国王找到了你,希望你能帮助他完成这个任务。

主任当然知道这道题怎么做,但是主任不高兴做了,于是他就找到了你,让你解决掉这道题。

Input Format

第一行是正整数N,M,K,表示S国城市数量和道路数量,以及T国国王愿意修缮的道路数量K。

接着M行每行三个正整数,Xi,Yi,Ti,分别表示城市Xi与Yi之间有一条双向道路连接,并且所需时间是Ti。

Output Format

一行,即修缮完后从城市1到城市N所需的最短时间。

Sample Input1

4 4 1
1 2 10
2 4 10
1 3 1
3 4 100

Sample Output1

1

Limits

N<=10000, M<=50000, K<=20

1<=Xi,Yi<=N, 1<=Ti<=1000000

yyong119's solution

#include <cstdio>
#include <iostream>
#include <deque>
#include <vector>
#include <cstring>
#include <algorithm>
#define MAX_N 10010
#define MAX_K 25
using namespace std;
struct Node {
    int tar, time;
    Node(int a = 0, int b = 0): tar(a), time(b) {}
};
int N, M, K;
int f[MAX_N][MAX_K];
vector<Node> link[MAX_N];
deque<int> q;
bool inque[MAX_N];
inline int read() {
    char ch = getchar(); int flag = 1, res = 0;
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') flag = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') res = res * 10 + ch - '0', ch = getchar();
    return res * flag;
}
inline bool cmp(const Node &p, const Node &q) {
    return p.time < q.time;
}
int main() {
    N = read(); M = read(); K = read();
    memset(f, 0x3f3f3f3f, sizeof(f));
    f[1][0] = 0;
    for (register int i = 0; i < M; ++i) {
        int x = read(), y = read(), t = read();
        link[x].push_back(Node(y, t));
        link[y].push_back(Node(x, t));
    }
    for (register int i = 0; i < N; ++i)
        sort(link[i].begin(), link[i].end(), cmp);
    q.push_back(1);
    while (!q.empty()) {
        int cur = q.front(); q.pop_front(); inque[cur] = false;
        for (register int i = 0; i < link[cur].size(); ++i) {
            int next = link[cur][i].tar, cost = link[cur][i].time;
            bool flag = false;
            for (register int j = 0; j <= K; ++j)
                if (f[cur][j] + cost < f[next][j]) {
                    f[next][j] = f[cur][j] + cost;
                    flag = true;
                }
            for (register int j = 0; j < K; ++j)
                if (f[cur][j] < f[next][j + 1]) {
                    f[next][j + 1] = f[cur][j];
                    flag = true;
                }
            if (!inque[next] && flag) {
                if (!q.empty() && f[next][K] >= f[q.front()][K]) q.push_back(next);
                else q.push_front(next);
                inque[next] = true;
            }
        }
    }
    printf("%d\n", f[N][K]);
    return 0;
}