Skip to content

14072: 【原4072】日天卖面包

题目

题目描述

author: MW 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/4072

Description

日天想要开一家面包店,卖各种各样的面包,他决定把店开在n个城市中的1个,这些城市的编号从1到n。而这些城市之间有m条道路,每一条连接着两个城市。

为了能在面包店里烤面包,日天需要一些制造面包的原料,而这些原料只在一些城市里有。k个原料城市分别在\(a_1,a_2,\cdots,a_k, 且a_i\in [1,n]\)

然而不幸的是,当地有一个政策,面包店不能开在有原料的城市里,因此他只能将面包店开在另外的n-k个城市中。当然,原料是要有运输费用的,日天需要为每1道路长度支付1元。

更严谨的说,如果日天吧面包店开在某一个城市b\((a_i \not= b 对于任意的 1\leq i \leq k)\), 并选择了一个有原料的城市s(s \( = a_j, 对某一j,1\leq j\leq k)\),并且b和s被一些路径连接在一起,这些路径的长度之和为x (如果有多条路径,日天可以选择他想要的那一条路径),则日天需要支付x元。

日天想要让自己的面包店成本最低,所以需要最低的运费。

Input Format

第一行,有三个整数n, m, k,分别对应城市数,道路数和有原料城市的数量。

接下来的m行,每一行包含三个整数u, v, l (\(u\not=v\)),表示城市u和v之间有一条长度为l的道路。

如果k > 0,那么最后一行会有k个不同的整数\(a_1, a_2, \cdots, a_k\),表示各个有原料城市的编号。如果k = 0,这一行不会出现。

Output Format

输出日天需要支付的最少的运费。

如果不存在能够开面包店的城市,则输出-1

Sample Input 1

5 4 2
1 2 5
1 2 3
2 3 4
1 4 10
1 5

Sample Output 1

3

Sample Input 2

3 1 1
1 2 3
3

Sample Output 2

-1

Limits

对于50%的数据,\(1\leq n \leq 20\)

对于100%的数据,\(1\leq n, m \leq 1e5\)

其中\(1\leq k \leq n, 1\leq l\leq 1e9\)

FineArtz's solution

/* 日天卖面包 */
#include <iostream>
#include <map>
#include <set>
#include <algorithm>
#include <cstring>
using namespace std;

class Point{
public:
    map<int, int> edge;
};

Point a[100005];
set<int> s;
bool is[100005];
int n, m, k;

int main(){
    cin >> n >> m >> k;
    if (k == 0){
        cout << "-1" << endl;
        return 0;
    }
    if (n >= 50){
    memset(is, 0, sizeof(is));
    for (int i = 1; i <= m; ++i){
        int u, v, w;
        cin >> u >> v >> w;
        if (a[u].edge.find(u) == a[u].edge.end()){
            a[u].edge[v] = w;
            a[v].edge[u] = w;
        }
        else{
            if (a[u].edge[v] > w){
                a[u].edge[v] = w;
                a[v].edge[u] = w;
            }
        }
    }
    int ans = 2147483647;
    int t;
    for (int i = 1; i <= k; ++i){
        cin >> t;
        s.insert(t);
        is[t] = true;
    }
    for (auto i : s){
        for (auto j : a[i].edge){
            if (!is[j.first]){
                ans = min(ans, j.second);
            }
        }
    }
    if (ans == 2147483647)
        cout << "-1" << endl;
    else
        cout << ans << endl;
    }
    else{
        int a[25][25];
        for (int i = 0; i < 25; ++i)
            for (int j = 0; j < 25; ++j)
                a[i][j] = -1;
        for (int i = 1; i <= m; ++i){
            int u, v, w;
            cin >> u >> v >> w;
            if (a[u][v] == -1){
                a[u][v] = w;
                a[v][u] = w;
            }
            else{
                if (a[u][v] > w){
                    a[u][v] = w;
                    a[v][u] = w;
                }
            }
        }
        int s[25];
        bool is[25];
        memset(is, 0, sizeof(is));
        for (int i = 1; i <= k; ++i){
            cin >> s[i];
            is[s[i]] = true;
        }
        int ans = 2147483647;
        for (int i = 1; i <= k; ++i){
            for (int j = 1; j <= n; ++j){
                if (is[j]) continue;
                if (a[s[i]][j] == -1) continue;
                ans = min(ans, a[s[i]][j]);
            }
        }
        if (ans == 2147483647)
            cout << "-1" << endl;
        else
            cout << ans << endl;
    }
    return 0;
}

ligongzzz's solution

#include "iostream"
#include "cstdio"
using namespace std;

bool city[100001] = { 0 };
int road[100000][3] = { 0 };

int main() {
    int n, m, k;
    cin >> n >> m >> k;

    for (int i = 0; i < m; i++) {
        scanf("%d %d %d", &road[i][0], &road[i][1], &road[i][2]);
    }

    for (int i = 0; i < k; i++) {
        int temp;
        scanf("%d", &temp);
        city[temp] = true;
    }

    //寻找最短路
    long long minMoney=1e10;
    for (int i = 0; i < m; i++) {
        if ((city[road[i][0]] && !city[road[i][1]]) || (!city[road[i][0]] && city[road[i][1]])) {
            if (road[i][2] < minMoney)
                minMoney = road[i][2];
        }
    }

    if (k == 0 || minMoney >= 1e10)
        cout << -1;
    else
        cout << minMoney;

    return 0;
}