【2019南昌ネットワークコンペティション】Bファイアファイティングヒーロー

トピックリンク

分析

ヒーローの側面は非常にシンプルで、ダイクストラを1回実行するだけですが、消防チームは少し面倒です。

ここで
、最大フローエッジの構築によってこの問題を解決できます。開始点として別のポイントを見つけ、そのポイントから各チームの開始ポイントへの重みを0にしてエッジを作成し、最短のマルチスタートポイントを完成させます。道路

たまたま私のボードはパッケージされたダイクストラであるので、問題を解決するために2つの構造を直接作成しました。ポイントの数は1,000だけなので、スペースの心配はありません。

ACコード

#include <bits/stdc++.h>

using namespace std;

#define MAXN 1100
#define MAXM 1000000

#define INF 0x3fffffff              //防止后面溢出,这个不能太大

struct Graph {
    
    
    struct Edge {
    
    
        long long to, next;
        long long cost;
    } edge[MAXM];
    long long head[MAXN];
    long long tot;

    void init(long long n) {
    
    
        tot = 0;
        memset(head, -1, sizeof(long long) * (n + 1));
    }

    void add_edge(long long from, long long to, long long value) {
    
    
        edge[tot].to = to;
        edge[tot].cost = value;
        edge[tot].next = head[from];
        head[from] = tot++;
    }
};

struct Dijkstra {
    
    
    long long low_cost[MAXN];
    bool vis[MAXN];
    long long pre[MAXN];

    void solve(long long b, long long e, long long start, Graph &graph) {
    
    
        for (long long i = b; i < e; i++) {
    
    
            low_cost[i] = INF;
            vis[i] = false;
            pre[i] = -1;
        }
        low_cost[start] = 0;
        vis[start] = true;
        long long cur_edge = graph.head[start];
        while (cur_edge != -1) {
    
    
            if (!vis[graph.edge[cur_edge].to] &&
                low_cost[start] + graph.edge[cur_edge].cost < low_cost[graph.edge[cur_edge].to]) {
    
    
                low_cost[graph.edge[cur_edge].to] = low_cost[start] + graph.edge[cur_edge].cost;
                pre[graph.edge[cur_edge].to] = start;
            }
            cur_edge = graph.edge[cur_edge].next;
        }
        for (long long j = b; j < e - 1; j++) {
    
    
            long long k = -1;
            long long Min = INF;
            for (long long i = b; i < e; i++) {
    
    
                if (!vis[i] && low_cost[i] < Min) {
    
    
                    Min = low_cost[i];
                    k = i;
                }
            }
            if (k == -1)
                break;
            vis[k] = true;
            cur_edge = graph.head[k];
            while (cur_edge != -1) {
    
    
                if (!vis[graph.edge[cur_edge].to] &&
                    low_cost[k] + graph.edge[cur_edge].cost < low_cost[graph.edge[cur_edge].to]) {
    
    
                    low_cost[graph.edge[cur_edge].to] = low_cost[k] + graph.edge[cur_edge].cost;
                    pre[graph.edge[cur_edge].to] = k;
                }
                cur_edge = graph.edge[cur_edge].next;
            }
        }
    }
};

Graph graph;
Dijkstra dijkstra1, dijkstra2;
int k_node[MAXN];

void solve() {
    
    
    long long t;
    cin >> t;
    long long v, e, s, k, c;
    for (int ts = 0; ts < t; ++ts) {
    
    
        cin >> v >> e >> s >> k >> c;
        graph.init(v + 1);
        for (int i = 0; i < k; ++i) {
    
    
            cin >> k_node[i];
        }
        long long from, to, value;
        for (long long i = 0; i < e; ++i) {
    
    
            cin >> from >> to >> value;
            graph.add_edge(from, to, value);
            graph.add_edge(to, from, value);
        }
        dijkstra1.solve(1, v + 1, s, graph);//第一次跑dijkstra
        for (int i = 0; i < k; ++i) {
    
    
            graph.add_edge(0, k_node[i], 0); // 这里设定超级源点为0,建立从0到每一个团队起点的边,权值为0
        }
        dijkstra2.solve(0, v + 1, 0, graph);//第二次跑dijkstra

        long long s_min_max = 0;
        for (long long i = 1; i < v + 1; ++i)
            s_min_max = max(s_min_max, dijkstra1.low_cost[i]);

        long long k_min_max = 0;
        for (long long i = 1; i < v + 1; ++i)
            k_min_max = max(k_min_max, dijkstra2.low_cost[i]);

        if (s_min_max <= c * k_min_max)//考虑到精度问题,这里用乘法代替
            cout << s_min_max << endl;
        else
            cout << k_min_max << endl;
    }
}

int main() {
    
    
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    long long test_index_for_debug = 1;
    char acm_local_for_debug;
    while (cin >> acm_local_for_debug) {
    
    
        cin.putback(acm_local_for_debug);
        if (test_index_for_debug > 100) {
    
    
            throw runtime_error("Check the stdin!!!");
        }
        auto start_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << ":" << endl;
        solve();
        auto end_clock_for_debug = clock();
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "\n--------------------------------------------------" << endl;
    }
#else
    solve();
#endif
    return 0;
}

おすすめ

転載: blog.csdn.net/m0_43448982/article/details/100651025