跳转至

day4

[ABC416E] Development

代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int N = 5e2 + 5;
int n, m, k, t, q, f[N][N];
signed main()
{
    ios::sync_with_stdio(false), cin.tie(0);
    cin >> n >> m;
    for (int i = 0; i <= n; i++)
        for (int j = 0; j <= n; j++)
            if (i != j)
                f[i][j] = 1e18;
    while (m--)
    {
        int u, v, w;
        cin >> u >> v >> w;
        f[u][v] = f[v][u] = min(f[u][v], w);
    }
    cin >> k >> t;
    for (int i = 1; i <= k; i++)
    {
        int x;
        cin >> x;
        f[x][0] = t;
        f[0][x] = 0;
    }
    for (int k = 0; k <= n; k++)
        for (int i = 0; i <= n; i++)
            for (int j = 0; j <= n; j++)
                f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
    cin >> q;
    while (q--)
    {
        int op;
        cin >> op;
        if (op == 1)
        {
            int u, v, w;
            cin >> u >> v >> w;
            f[u][v] = f[v][u] = min(f[u][v], w);
            for (int i = 0; i <= n; i++)
            {
                for (int j = 0; j <= n; j++)
                {
                    f[i][j] = min(f[i][j], f[i][u] + w + f[v][j]);
                    f[i][j] = min(f[i][j], f[i][v] + w + f[u][j]);
                }
            }
        }
        if (op == 2)
        {
            int x;
            cin >> x;
            f[x][0] = t;
            f[0][x] = 0;
            for (int i = 0; i <= n; i++)
            {
                for (int j = 0; j <= n; j++)
                {
                    f[i][j] = min(f[i][j], f[i][x] + t + f[0][j]);
                    f[i][j] = min(f[i][j], f[i][0] + 0 + f[x][j]);
                }
            }
        }
        if (op == 3)
        {
            int ans = 0;
            for (int i = 1; i <= n; i++)
                for (int j = 1; j <= n; j++)
                    if (f[i][j] != 1e18)
                        ans += f[i][j];
            cout << ans << "\n";
        }
    }
    return 0;
}

[CSP-S 2022] 假期计划

暴力 $60$ 分

\[ \begin{array}{ll} 1 & \textbf{for } a \gets 2 \textbf{ to } n \\ 2 & \qquad \textbf{if } f[1][a] > k + 1 \textbf{ then continue} \\ 3 & \qquad \textbf{for } b \gets 2 \textbf{ to } n \\ 4 & \qquad\qquad \textbf{if } f[a][b] > k + 1 \ \textbf{or } a=b \textbf{ then continue} \\ 5 & \qquad\qquad \textbf{for } c \gets 2 \textbf{ to } n \\ 6 & \qquad\qquad\qquad \textbf{if } f[b][c] > k + 1 \ \textbf{or } b=c \ \textbf{or } a=c \textbf{ then continue} \\ 7 & \qquad\qquad\qquad \textbf{for } d \gets 2 \textbf{ to } n \\ 8 & \qquad\qquad\qquad\qquad \textbf{if } f[c][d] > k + 1 \ \textbf{or } f[d][1] > k + 1 \ \textbf{or } d \in \{a,b,c\} \textbf{ then continue} \\ 9 & \qquad\qquad\qquad\qquad\qquad ans \gets \max(ans, \ s[a]+s[b]+s[c]+s[d]) \\ \end{array} \]
满分代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2.5e3 + 5;
int n, m, k, w[N], f[N][N], ans;
vector<int> e[N];
vector<int> g[N]; // 预处理每个点可以到哪些点
void bfs(int s, int dis[])
{
    queue<int> q;
    q.push(s);
    dis[s] = 0; 
    while (q.size())
    {
        int u = q.front();
        q.pop();
        for (auto v : e[u])
        {
            if (dis[v] == 1e9)
            {
                dis[v] = dis[u] + 1;
                // 保留可达的点,1 号点不要,其次要保证 1 可以在 k 步内到达,且 s 到达 v 也可以在 k 步以内。
                if (v != 1 && f[1][v] <= k && dis[v] <= k)
                {
                    g[s].push_back(v); // s 可以到 v
                }
                if (g[s].size() > 3) // 个数多于 3,删除权值较小的点
                {
                    sort(g[s].begin(), g[s].end(), [&](int x, int y) {
                        return w[x] > w[y];
                    });
                    g[s].pop_back(); // 删除权值小的
                }    
                q.push(v);
            }
        }
    }
}
int main()
{
    cin >> n >> m >> k;
    k++; // 直接令 k + 1 即可
    for (int i = 2; i <= n; i++) cin >> w[i];
    while (m--)
    {
        int x, y;
        cin >> x >> y;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            f[i][j] = 1e9; // 初始化最短路不存在
        }
        bfs(i, f[i]);
    }
    for (int b = 2; b <= n; b++)
    {
        for (int c = 2; c <= n; c++)
        {
            if (b == c || f[b][c] > k) continue;
            for (auto a : g[b])
            {
                for (auto d : g[c])
                {
                    if (a == d || a == c || d == b) continue;
                    if (f[1][a] > k || f[a][b] > k || f[c][d] > k || f[d][1] > k) continue;
                    ans = max(ans, w[a] + w[b] + w[c] + w[d]); 
                }
            }
        }
    }
    cout << ans;
    return 0;
}

[TJOI2019] 大中锋的游乐场

满分代码
#include <bits/stdc++.h>
using namespace std;
using ary = array<int, 2>;

void solve()
{
    int n, m, k;
    cin >> n >> m >> k;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        // 这里为了方便将汉堡设为 -1
        if (a[i] == 2)
            a[i] = -1;
    }
    vector<vector<ary>> e(n + 1);
    while (m--)
    {
        int u, v, w;
        cin >> u >> v >> w;
        e[u].push_back({v, w});
        e[v].push_back({u, w});
    }
    int s, t;
    cin >> s >> t;
    vector<vector<int>> dis(n + 1, vector<int>(25, 1e9)), vis(n + 1, vector<int>(25, 0));
    // dis[i][j] : 走到点 i 且可乐减去汉堡差值为 j 的最短路
    // 堆里存储三个信息,[距离,差值,编号]
    priority_queue<array<int, 3>, vector<array<int, 3>>, greater<array<int, 3>>> q;
    // 初始化起点
    dis[s][a[s] + 10] = 0;
    q.push({0, a[s] + 10, s});
    while (q.size())
    {
        auto [d, i, u] = q.top();
        q.pop();
        // Dijkstra:已经加入 S 集合代表最短路已确定就跳过
        if (vis[u][i])
            continue;
        vis[u][i] = 1;
        // auto [v, w] 结构化绑定 C++ 17语法,信奥赛目前禁用
        for (auto [v, w] : e[u])
        {
            if (a[v] == 1 && abs(i + 1 - 10) <= k) // 买了可乐
            {
                int j = i + 1;
                if (dis[v][j] > dis[u][i] + w)
                {
                    dis[v][j] = dis[u][i] + w;
                    q.push({dis[v][j], j, v});
                }
            }
            if (a[v] == -1 && abs(i - 1 - 10) <= k)
            {
                int j = i - 1;
                if (dis[v][j] > dis[u][i] + w)
                {
                    dis[v][j] = dis[u][i] + w;
                    q.push({dis[v][j], j, v});
                }
            }
        }
    }
    // min_element 返回最小值的迭代器(指针),通过 * 解引用获取具体的值。
    int ans = *min_element(dis[t].begin(), dis[t].end());
    if (ans == 1e9)
        ans = -1;
    cout << ans << "\n";
}
int main()
{
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}

[Code+#4] 最短路

满分代码
#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int N, M, C;
    cin >> N >> M >> C;
    vector<vector<pair<int, int>>> e(N + 1);
    // 读取 M 条特殊边
    for (int i = 0; i < M; i++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        e[u].push_back({v, w});
    }
    // 普通异或边:逐位翻转。注意 0 号点也要考虑进来
    for (int i = 0; i <= N; i++)
    {
        for (int k = 0; k <= 16; k++) // n 最多 1e5,至多考虑到 2 的 16 次方即可
        {
            int j = i ^ (1 << k);
            if (j <= N)
            {
                e[i].push_back({j, (1 << k) * C});
            }
        }
    }
    int A, B;
    cin >> A >> B;
    // Dijkstra
    vector<long long> dist(N + 1, 1e18);
    vector<bool> vis(N + 1, false);
    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;
    dist[A] = 0;
    pq.push({0, A});
    while (!pq.empty())
    {
        auto [d, u] = pq.top();
        pq.pop();
        if (vis[u])
            continue;
        vis[u] = true;
        for (auto it : e[u])
        {
            int v = it.first, w = it.second;
            if (dist[v] > d + w)
            {
                dist[v] = d + w;
                pq.push({dist[v], v});
            }
        }
    }
    cout << dist[B] << "\n";
    return 0;
}

[GXOI/GZOI2019] 旅行者

满分代码
#include <bits/stdc++.h>
#define ll long long
#define f first
#define s second
using namespace std;
typedef pair<int, int> p;
const int N = 1e5 + 5;
ll n, m, dis[N], k, st, ed, a[N];
bool vis[N];
vector<p> e[N], t[N];
struct node
{
    ll id, d; // 编号,距离
    bool operator < (const node&x) const
    {
        return d > x.d;
    }
};
void dijkstra()
{
    priority_queue<node> q;
    memset(vis, 0, sizeof(vis));
    memset(dis, 0x7f, sizeof(dis));
    dis[0] = 0;
    q.push({0, 0});
    while (q.size())
    {
        node now = q.top();
        q.pop();
        int u = now.id, distance = now.d;
        if (vis[u]) continue;
        vis[u] = 1;
        for (auto x : e[u])
        {
            int v = x.f, w = x.s;
            if (dis[v] > dis[u] + w)
            {
                dis[v] = dis[u] + w;
                q.push({v, dis[v]});
            }
        }
    }
}
void init()
{
    for (int i = 0; i <= n + 1; i++) e[i].clear(), e[i] = t[i];
}
void solve()
{
    cin >> n >> m >> k;
    for (int i = 0; i <= n + 1; i++) e[i].clear(), t[i].clear();
    while (m--)
    {
        int u, v, w;
        cin >> u >> v >> w;
        e[u].push_back({v, w});
        t[u].push_back({v, w});
    }
    for (int i = 1; i <= k; i++) cin >> a[i];
    ll ans = 1e18;
    for (int i = 0; (1 << i) <= n; i++)
    {
        init();
        for (int j = 1; j <= k; j++)
        {
            if (a[j] >> i & 1) e[0].push_back({a[j], 0});
            else e[a[j]].push_back({n + 1, 0});
        }
        dijkstra();
        ans = min(ans, dis[n + 1]);
        init();
        for (int j = 1; j <= k; j++)
        {
            if (a[j] >> i & 1) e[a[j]].push_back({n + 1, 0});
            else e[0].push_back({a[j], 0});
        }
        dijkstra();
        ans = min(ans, dis[n + 1]);
    }
    cout << ans << "\n";
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t = 1;
    cin >> t;
    while (t--) solve();
    return 0;
}

[COCI2009-2010#7] SVEMIR

满分代码
#include <bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
#define fi first
#define se second
#define re register
using namespace std;
typedef pair<ll, ll> pi;
const int N = 1e5 + 5;
int n, fa[N];
ll ans;
struct edge
{
    ll u, v, w;
    bool operator < (const edge&x) const
    {
        return w < x.w;
    }
};
vector<edge> e;
struct Node
{
    int x, y, z, id;
} node[N];
bool cmp1(Node a, Node b) { return a.x < b.x; }
bool cmp2(Node a, Node b) { return a.y < b.y; }
bool cmp3(Node a, Node b) { return a.z < b.z; }
ll find(int x)
{
    if (x != fa[x])
    {
        return fa[x] = find(fa[x]);
    }
    return fa[x];
}
void join(int x, int y)
{
    x = find(x), y = find(y);
    fa[x] = y;
    return ;
}
int main()
{

    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++) fa[i] = i;
    for (int i = 1; i <= n; i++)
    {
        cin >> node[i].x >> node[i].y >> node[i].z;
        node[i].id = i;
    }
    sort(node + 1, node + n + 1, cmp1);
    for (int i = 2; i <= n; i++) e.pb({node[i].id, node[i - 1].id, node[i].x - node[i - 1].x});
    sort(node + 1, node + n + 1, cmp2);
    for (int i = 2; i <= n; i++) e.pb({node[i].id, node[i - 1].id, node[i].y - node[i - 1].y});
    sort(node + 1, node + n + 1, cmp3);
    for (int i = 2; i <= n; i++) e.pb({node[i].id, node[i - 1].id, node[i].z - node[i - 1].z});
    sort(e.begin(), e.end());
    int num = 0;
    for (int i = 0; i < e.size(); i++)
    {
        int u = e[i].u, v = e[i].v;
        ll w = e[i].w;
        if (find(u) != find(v))
        {
            join(u, v);
            num++;
            ans += w;
            if (num == n - 1) break;
        }
    }
    cout << ans;
    return 0;
}

[ABC364F] Range Connect MST

满分代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using pii = pair<int, int>;
using pli = pair<i64, int>;
template <typename T>
using vec = vector<T>;
struct dsu
{
    int n;
    vec<int> p, siz;
    dsu(int n)
    {
        this->n = n;
        p.assign(n + 1, 0), siz.assign(n + 1, 1);
        iota(p.begin(), p.end(), 0);
    }
    int find(int x)
    {
        return x == p[x] ? x : p[x] = find(p[x]);
    }
    void merge(int x, int y)
    {
        x = find(x), y = find(y);
        if (x == y) return;
        if (siz[x] > siz[y]) swap(x, y);
        p[x] = y;
        siz[y] += siz[x];
    }
    int sz(int x) { return siz[find(x)]; }
};
int main()
{
    ios::sync_with_stdio(false), cin.tie(0);
    int n, q;
    cin >> n >> q;
    vec<array<int, 3>> que(q);
    for (int i = 0; i < q; i++)
    {
        cin >> que[i][1] >> que[i][2] >> que[i][0];
    }
    sort(que.begin(), que.end());
    i64 ans = 0, num = 0;
    dsu d(n + 1); 
    for (auto [c, l, r] : que)
    {
        ans += c; 
        for (int i = d.find(l); i < r; i = d.find(i + 1))
        {
            ans += c;
            num++;
            d.p[i] = i + 1;
        }
    }
    if (num != n - 1) cout << -1;
    else cout << ans;
    return 0;
}