hdu 3499 (最短路)

題目:http://acm.hdu.edu.cn/showproblem.php?pid=3499
題意:給定一個有向帶權圖,點數n <= 1e5 邊數 m <= 5 * 1e5, 可以選擇任意一條邊將其權值減半, 求s到t的最短路。

解法: 做兩遍單源最短路, 一遍正向,一遍反向,枚舉每條邊<u, v>, 將其權值減半,所求答案即爲min{dis[s → u] + dis[t → v] + w / 2}, 複雜度爲最短路複雜度。


#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
using namespace std;

#define mp make_pair
#define se second
#define fi first

const int N = 100005;
const int M = 500005;
const int C = 62;
const long long INF = 1LL << 60;
typedef long long LL;
typedef pair<LL, int> P;
int n, m;
int map[256];

void init() {
    for (int i = 0; i < 26; i++)
        map[i + 'A'] = i;
    for (int i = 0; i < 26; i++)
        map[i + 'a'] = i + 26;
    for (int i = 0; i < 10; i++)
        map[i + '0'] = i + 52;
}

struct Edge {
    Edge* next;
    int v, w;

    void init(int a, int b, Edge* e) {
        next = e, v = a, w = b;
    }
};

struct Dijkstra {
    Edge E[M], * head[N];
    priority_queue<P, vector<P>, greater<P> > pq;
    LL dis[N];
    int tot;

    void init() {
        for (int i = 0; i < n; i++)
            head[i] = 0;
        tot = 0;
    }

    void add(int u, int v, int w) {
        E[tot].init(v, w, head[u]);
        head[u] = &E[tot++];
    }

    void solve(int s) {
        for (int i = 0; i < n; i++)
            dis[i] = INF;
        dis[s] = 0LL;
        pq.push(mp(0LL, s));
        while (!pq.empty()) {
            P cur = pq.top();
            pq.pop();
            int u = cur.se;
            if (cur.fi != dis[u]) continue;
            for (Edge* e = head[u]; e; e = e->next) {
                int v = e->v;
                if (dis[v] > dis[u] + e->w) {
                    dis[v] = dis[u] + e->w;
                    pq.push(mp(dis[v], v));
                }
            }
        }
    }
}G1, G2;

struct Trie {
    int ch[N][C], val[N];
    int sz, id;

    void init() {
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
        id = 0;
    }

    int find(char* s) {
        int u = 0;
        for (int i = 0; s[i]; i++) {
            int c = map[s[i]];
            if (!ch[u][c]) {
                memset(ch[sz], 0, sizeof(ch[sz]));
                val[sz] = -1;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        if (val[u] == -1)
            val[u] = id++;
        return val[u];
    }
}T;

char u[100], v[100];

int main() {
    int w;
    init();
    while (~scanf("%d%d", &n, &m)) {
        T.init();
        G1.init(), G2.init();
        for (int i = 0; i < m; i++) {
            scanf("%s%s%d", u, v, &w);
            int a1 = T.find(u), a2 = T.find(v);
            G1.add(a1, a2, w);
            G2.add(a2, a1, w);
        }
        scanf("%s%s", u, v);
        int s = T.find(u), t = T.find(v);
        G1.solve(s);
        G2.solve(t);
        LL ans = INF;
        for (int i = 0; i < n; i++)
            for (Edge* e = G1.head[i]; e; e = e->next) {
                int v = e->v;
                ans = min(ans, G1.dis[i] + G2.dis[v] + (e->w / 2));
            }
        if (ans != INF)
            printf("%I64d\n", ans); // hdu寫法
        else
            puts("-1");
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章