Wannafly挑战赛2 B.Travel 最短路+思维

Posted kaka0010

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Wannafly挑战赛2 B.Travel 最短路+思维相关的知识,希望对你有一定的参考价值。

原题链接:https://ac.nowcoder.com/acm/contest/17/B

题意

先给你一个n个点组成的环,现在在上面加m条边,m小于20,最后询问任意两点之间的最短路。

分析

先从m入手,m非常小,因此肯定是从m条边连接的点出发,去跑2m遍最短路,预处理出这2m个点到图上所有点的最短路。

对于xy之间的最短路一定只有三种情况:

  1. 不经过后加的边,那可以O1直接算出值
  2. x到u,u到v,v到y
  3. x到v,v到u,u到y

因此暴力枚举所有加边,对于这三种情况取一个最小值就可以了。
这题有点卡内存

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int ul;
typedef pair<int, int> PII;
const ll inf = 1e18;
const int N = 55500;
const int M = 1e6 + 10;
const ll mod = 1e9 + 7;
const double eps = 1e-8;

#define lowbit(i) (i & -i)
#define Debug(x) cout << (x) << endl
#define fi first
#define se second
#define mem memset
#define endl '\\n'

namespace StandardIO {
    template<typename T>
    inline void read(T &x) {
        x = 0; T f = 1;
        char c = getchar();
        for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
        for (; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - '0';
        x *= f;
    }

    template<typename T>
    inline void write(T x) {
        if (x < 0) putchar('-'), x *= -1;
        if (x >= 10) write(x / 10);
        putchar(x % 10 + '0');
    }
}
namespace Comb {
    ll f[N];
    ll ksm(ll a, ll b) {
        ll res = 1, base = a;
        while (b) {
            if (b & 1) res = res * base % mod;
            base = base * base % mod;
            b >>= 1;
        }
        return res;
    }
    void init() {
        f[0] = 1;
        for (ll i = 1; i < N; i++) f[i] = f[i - 1] * i % mod;
    }
    ll C(ll a, ll b) {
        if (a < 0 || b < 0 || b > a) return 0;
        return f[a] * ksm(f[a - b], mod - 2) % mod * ksm(f[b], mod - 2) % mod;
    }
}
namespace Seg {
#define ls (u<<1)
#define rs (u<<1|1)
#define mid ((l+r)>>1)
    ll sum[N<<2], tag[N<<2];
    void push_up(int u) {
        sum[u] = sum[u<<1] + sum[u<<1|1];
    }
    void push_down(int u, int l, int r) {
        if (tag[u]) {
            tag[u<<1] += tag[u];
            tag[u<<1|1] += tag[u];
            sum[u<<1] += 1ll*(mid-l+1)*tag[u];
            sum[u<<1|1] += 1ll*(r-mid)*tag[u];
            tag[u] = 0;
        }
    }
    void modify(int u, int ql, int qr, int l, int r, int val) {
        if (ql <= l && qr >= r) {
            sum[u] += 1ll*(r-l+1)*val;
            tag[u] += val;
            return;
        }
        push_down(u, l, r);
        if (ql <= mid) modify(ls, ql, qr, l, mid, val);
        if (qr > mid) modify(rs, ql, qr, mid+1, r, val);
        push_up(u);
    }
}
namespace ST {
    int mi[N][21], ma[N][21], lg[N], a[N], gcd[N][21];
    int cmp1(int x, int y) {
        return a[x] < a[y] ? x : y;
    }
    int cmp2(int x, int y) {
        return a[x] > a[y] ? x : y;
    }
    void init(int n) {
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
            gcd[i][0] = a[i];
            ma[i][0] = mi[i][0] = i, lg[i] = log2(i);
        }
        for (int i = 1; i <= 20; i++) {
            for (int j = 1; j + (1 << i) - 1 <= n; j++) {
                mi[j][i] = cmp1(mi[j][i - 1], mi[j + (1 << (i - 1))][i - 1]);
                ma[j][i] = cmp2(ma[j][i - 1], ma[j + (1 << (i - 1))][i - 1]);
                gcd[j][i] = __gcd(gcd[j][i - 1], gcd[j + (1 << (i - 1))][i - 1]);
            }
        }
    }
    int qry_mi(int l, int r) {
        int k = lg[r - l + 1];
        return a[cmp1(mi[l][k], mi[r - (1 << k) + 1][k])];
    }
    int qry_ma(int l, int r) {
        int k = lg[r - l + 1];
        return a[cmp2(ma[l][k], ma[r - (1 << k) + 1][k])];
    }
    int qry_pmi(int l, int r) {
        int k = lg[r - l + 1];
        return cmp1(mi[l][k], mi[r - (1 << k) + 1][k]);
    }
    int qry_pma(int l, int r) {
        int k = lg[r - l + 1];
        return cmp2(ma[l][k], ma[r - (1 << k) + 1][k]);
    }
    int qry_gcd(int l, int r) {
        int k = lg[r - l + 1];
        return __gcd(gcd[l][k], gcd[r - (1 << k) + 1][k]);
    }
}
struct Edge {
    int to, next, w;
}e[N<<1];
int cnt, h[N];
void add(int u, int v, int w) {
    e[cnt].to = v;
    e[cnt].w = w;
    e[cnt].next = h[u];
    h[u] = cnt++;
}
struct Bridge {
    int u, v, w;
};
vector<Bridge> E;
ll dis[41][N], pre[N];
int vis[N], d[N];
struct node {
    ll d;
    int now;
    bool operator < (const node &rhs) const {
        return d > rhs.d;
    }
};
map<int, int> id;
void dij(int st) {
    priority_queue<node> que;
    int ID = id[st];
    memset(vis, 0, sizeof vis);
    memset(dis[ID], 0x3f, sizeof dis[ID]);
    dis[ID][st] = 0;
    que.push({0, st});
    while (que.size()) {
        int now = que.top().now;
        que.pop();
        if (vis[now]) continue;
        vis[now] = 1;
        for (int i = h[now]; ~i; i = e[i].next) {
            int v = e[i].to;
            if (dis[ID][v] > dis[ID][now] + e[i].w) {
                dis[ID][v] = dis[ID][now] + e[i].w;
                if (!vis[v]) {
                    que.push({dis[ID][v], v});
                }
            }
        }
    }
}
inline void solve() {
    int n, m; cin >> n >> m;
    memset(h, -1, sizeof h);
    for (int i = 1; i <= n; i++) {
        cin >> d[i]; pre[i] = pre[i - 1] + d[i];
        add(i, i % n + 1, d[i]);
        add(i % n + 1, i, d[i]);
    }

    for (int i = 1; i <= m; i++) {
        int u, v, w; cin >> u >> v >> w;
        add(u, v, w), add(v, u, w);
        E.push_back({u, v, w});
    }
    int tot = 0;
    for (auto it : E) {
        if (!id[it.u]) id[it.u] = ++tot;
        if (!id[it.v]) id[it.v] = ++tot;
        dij(it.u);
        dij(it.v);
    }
    int q; cin >> q; while (q--) {
        int x, y; cin >> x >> y;
        if (x > y) swap(x, y);
        ll tmp = min(pre[y-1] - pre[x-1], pre[n-1] - pre[y-1] + d[n] + pre[x-1]);
        for (auto it : E) {
            tmp = min(dis[id[it.u]][x] + dis[id[it.v]][y] + it.w, tmp);
            tmp = min(dis[id[it.u]][y] + dis[id[it.v]][x] + it.w, tmp);
        }
        cout << tmp << endl;
    }
}

signed main()<

以上是关于Wannafly挑战赛2 B.Travel 最短路+思维的主要内容,如果未能解决你的问题,请参考以下文章

Wannafly挑战赛24

Wannafly挑战赛23 A字符串

Wannafly挑战赛18

Wannafly挑战赛13-C

Wannafly挑战赛22游记

Wannafly挑战赛2 Cut