P4043 [AHOI2014/JSOI2014] 上下界最小费用流

题意

传送门 P4043 [AHOI2014/JSOI2014]支线剧情

题解

游戏剧情构成一个 DAG,一次游戏花费的时间等于所走剧情路线花费的时间和。那么问题转化为边容量有上下界限制的最小费用流问题。设置超级汇点,与所有剧情点连边后,跑有源汇上下界最小费用流即可(基本思路是假设下界限制得到满足,然后尽量使流量平衡)。

#include <bits/stdc++.h>
using namespace std;
template <typename Cap, typename Cost>
struct MCF
{
    struct edge
    {
        int to;
        Cap cap;
        int rev;
        Cost cost;
    };
    int V;
    vector<vector<edge>> G;
    vector<Cost> h, ds;
    vector<int> prevv, preve;
    vector<bool> used;
    MCF(int n) : V(n), G(n), h(n), ds(n), prevv(n), preve(n), used(n) {}
    void add_edge(int from, int to, Cap cap, Cost cost)
    {
        G[from].push_back({to, cap, (int)G[to].size(), cost});
        G[to].push_back({from, 0, (int)G[from].size() - 1, -cost});
    }
    pair<Cap, Cost> min_cost_flow(int s, int t, Cap f = numeric_limits<Cap>::max())
    {
        Cost res = 0;
        while (f > 0)
        {
            priority_queue<pair<Cost, int>, vector<pair<Cost, int>>, greater<pair<Cost, int>>> q;
            fill(ds.begin(), ds.end(), numeric_limits<Cost>::max());
            fill(used.begin(), used.end(), 0);
            ds[s] = 0;
            q.push({0, s});
            while (!q.empty())
            {
                int v = q.top().second;
                q.pop();
                if (used[v])
                    continue;
                used[v] = 1;
                for (int i = 0; i < (int)G[v].size(); ++i)
                {
                    auto &e = G[v][i];
                    Cost d = ds[v] + e.cost + h[v] - h[e.to];
                    if (e.cap > 0 && ds[e.to] > d)
                    {
                        ds[e.to] = d;
                        prevv[e.to] = v, preve[e.to] = i;
                        q.push({d, e.to});
                    }
                }
            }
            if (ds[t] == numeric_limits<Cost>::max())
                return {numeric_limits<Cap>::max() - f, res};
            for (int v = 0; v < V; ++v)
                h[v] += ds[v];
            Cap d = f;
            for (int v = t; v != s; v = prevv[v])
                d = min(d, G[prevv[v]][preve[v]].cap);
            f -= d;
            res += d * h[t];
            for (int v = t; v != s; v = prevv[v])
            {
                auto &e = G[prevv[v]][preve[v]];
                e.cap -= d;
                G[v][e.rev].cap += d;
            }
        }
        return {f, res};
    }
};

template <typename Cap, typename Cost>
struct edge
{
    int to;
    Cap lb, ub;
    Cost cost;
};
vector<vector<edge<int, int>>> G;

template <typename Cap, typename Cost>
pair<Cap, Cost> solve(int s, int t)
{
    int N = G.size();
    int S = N, T = S + 1;
    int V = T + 1;
    MCF<Cap, Cost> flow(V);

    vector<Cap> f(N);
    Cost add = 0;
    for (int v = 0; v < N; ++v)
        for (auto &e : G[v])
        {
            Cap x = e.lb;
            f[e.to] += x, f[v] -= x;
            add += x * e.cost;
        }
    Cap sum = 0;
    for (int v = 0; v < N; ++v)
    {
        if (f[v] > 0)
        {
            sum += f[v];
            flow.add_edge(S, v, f[v], 0);
        }
        else if (f[v] < 0)
            flow.add_edge(v, T, -f[v], 0);
    }

    for (int v = 0; v < N; ++v)
        for (auto &e : G[v])
            flow.add_edge(v, e.to, e.ub - e.lb, e.cost);
    flow.add_edge(t, s, numeric_limits<Cap>::max(), 0);

    auto res = flow.min_cost_flow(S, T);
    assert(sum == res.first);
    res.second += add;
    return res;
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0);
    int N;
    cin >> N;

    G.resize(N + 1);
    int inf = 1e9;
    for (int i = 0; i < N; ++i)
    {
        int k, b, t;
        cin >> k;
        for (int j = 0; j < k; ++j)
        {
            cin >> b >> t;
            G[i].push_back({b - 1, 1, inf, t});
        }
        G[i].push_back({N, 0, inf, 0});
    }

    auto res = solve<int, int>(0, N);
    cout << res.second << '\n';
    return 0;
}
AHOI2001是一种用于处理模式匹配和字符串搜索的经典算法,全称为"Another Happy Odyssey in 2001"。它通常应用于构建高效、空间优化的KMP(Knuth-Morris-Pratt)算法的一种改进版本。这种有限自动机常用于处理字符串搜索问题,尤其是在处理大量文本数据时。 关于题目代码的具体内容,这通常涉及到编程竞赛或算法实现题。通常,你需要编写一段程序,包括定义一个有限状态机(Finite Automaton),处理输入字符串和模式串,并根据AHOI2001算法来查找模式是否在原字符串中。关键部分会涉及如何创建前缀函数表、动态规划和自适应策略。 由于这不是一个直接的答案,下面是一个简化版的代码框架示例(假设用Python): ```python class AhoCorasickAutomaton: def __init__(self, patterns): self.prefix_func = self.build_prefix_function(patterns) def build_prefix_function(self, patterns): # 建立前缀函数表的计算过程... pass def search(self, text): index = 0 for pattern in patterns: while index < len(text) and index + len(pattern) <= len(text): if self.match(text[index:], pattern): return True index += self.prefix_func[pattern] return False def match(self, text, pattern): # 匹配函数,比较两个字符串是否相等... pass # 使用示例: patterns = ['AB', 'AC'] # 输入模式列表 automaton = AhoCorasickAutomaton(patterns) text = 'ABCABCD' # 待搜索的字符串 if automaton.search(text): print("Pattern found") else: print("Pattern not found")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值