侧边栏

2020 Multi-University Training Contest 4 1004- Deliver the Cake

链接

http://acm.hdu.edu.cn/showproblem.php?pid=6805

题意

n个点,每个点有属性,L,R或M
m条边,连接两点
现从s走到t,要求最短路
有一附加条件,L点用左手,R点用右手,M点均可,任意地方均可换手,换手时间为x

思路

裸的最短路,LR边的边权要多加x,LM和RM连边时将M拆成L点或R点去连,MM连边时将M拆成LL和RR去连
然后跑最短路就好了,因为边数组开小了所以一直T

代码

#include <bits/stdc++.h>
// #define inf 0x7f7f7f7f
#define ms(a) memset(a, 0, sizeof(a))
#define repu(i, a, b) for (int i = a; i < b; i++)
#define repd(i, a, b) for (int i = a; i > b; i--)
using namespace std;
typedef long long ll;
typedef long double ld;

const int M = int(1e5) * 2 + 5;
const int mod = int(1e9) + 7;
const ll inf = ll(1e18);
struct edge {
    ll to;
    ll w;
    ll next;
};
edge edges[M * 3];
int head[M];
int _cnt;
void add(ll u, ll v, ll w) {
    edges[_cnt].to = v;
    edges[_cnt].w = w;
    edges[_cnt].next = head[u];
    head[u] = _cnt++;
    edges[_cnt].to = u;
    edges[_cnt].w = w;
    edges[_cnt].next = head[v];
    head[v] = _cnt++;
}
void init() {
    _cnt = 0;
    memset(head, -1, sizeof(head));
}

struct node {
    ll v;
    ll cost;
    node(ll _v = 0, ll _c = 0) : v(_v), cost(_c) {}
    bool operator<(const node& b) const { return cost > b.cost; }
};
ll dis[M];
bool vis[M];

void dijkstra(ll n, ll start) {
    memset(vis, 0, sizeof(vis));
    for (int i = 1; i <= n; i++) dis[i] = inf;
    dis[start] = 0;
    priority_queue<node> pq;
    pq.push(node(start, 0));
    node tem;
    while (!pq.empty()) {
        tem = pq.top();
        pq.pop();
        ll u = tem.v;
        if (vis[u]) continue;
        vis[u] = 1;
        for (int i = head[u]; ~i; i = edges[i].next) {
            ll v = edges[i].to;
            if (dis[v] > dis[u] + edges[i].w) {
                dis[v] = dis[u] + edges[i].w;
                pq.push(node(v, dis[v]));
            }
        }
    }
}

int hand[M];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin >> t;
    while (t--) {
        init();
        ms(hand);
        ll n, m, s, t, x;
        cin >> n >> m >> s >> t >> x;
        string str;
        cin >> str;
        int tot = 0;
        repu(i, 0, str.size()) {
            if (str[i] == 'L') {
                hand[i + 1] = 1;
            } else if (str[i] == 'R') {
                hand[i + 1] = 2;
            } else {
                hand[i + 1] = 0;
                if ((i + 1) != s && (i + 1) != t) {
                    add(i + 1, i + n + 1, x);
                } else {
                    add(i + 1, i + 1 + n, 0);
                }
            }
        }

        repu(i, 0, m) {
            ll u, v, w;
            cin >> u >> v >> w;
            if (hand[u] == hand[v]) {
                add(u, v, w);
                if (!hand[u]) {
                    add(u + n, v + n, w);
                }
            } else {
                if (!hand[u]) {
                    if (hand[v] == 1) {
                        add(u, v, w);
                    } else {
                        add(u + n, v, w);
                    }
                } else if (!hand[v]) {
                    if (hand[u] == 1) {
                        add(u, v, w);
                    } else {
                        add(u, v + n, w);
                    }
                } else {
                    add(u, v, w + x);
                }
            }
        }
        dijkstra(n * 2 + 1, s);
        cout << dis[t] << endl;
    }
    return 0;
}

posted @ 2020-07-30 21:12  晴人  阅读(113)  评论(0编辑  收藏  举报