zoukankan      html  css  js  c++  java
  • 【2019 杭电多校第一场】Path 最短路+最小割

    题目链接

    题意

    给出一个 n 个点,m 条边的有向帯权图。

    摧毁一条边的代价为其权值,问使得 1 到 n 的最短路变长的最小代价是多少。

    思路

    上一年多校的时候还没有学习网络流,咋想都想不到

    首先我们求出一个最短路的新图,然后在新图上跑最小割即可。

    先求出 (1) 到其他点的距离 (dis_i),将 (n) 放到一个队列中,每次从队列取出一个点 (u)。遍历其反向边,如果(dis[v]+val==dis[u]),那么 (v)(u) 建一条权值为 val 的边,将 (v) 加入队列。

    忘了优先队列默认是按照从大到小排序,找了半天的bug。。。

    代码

    #include <bits/stdc++.h>
    #define fuck system("pause")
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll, ll> pll;
    typedef pair<int, int> pii;
    const int mod = 1e9 + 7;
    const int seed = 12289;
    const double eps = 1e-6;
    const int inf = 0x3f3f3f3f;
    const int N = 2e5 + 10;
    
    vector<pair<ll, ll>> vec[N], vec2[N];
    ll tot, head[N];
    struct Edge {
        ll to, next, val;
    } edge[N];
    void add(ll u, ll v, ll val)
    {
        edge[tot] = Edge { v, head[u], val };
        head[u] = tot++;
    }
    ll vis[N], dis[N];
    ll dijkstra(ll aga, ll en)
    {
        memset(vis, 0, sizeof(vis));
        memset(dis, 0x3f, sizeof(dis));
        dis[aga] = 0;
        priority_queue<pii, vector<pii>, greater<pii>> q;
        q.push({ 0, 1 });
        while (!q.empty()) {
            pair<ll, ll> temp = q.top();
            q.pop();
            ll u = temp.second;
            if (vis[u])
                continue;
            vis[u] = 1;
            for (ll i = 0; i < vec[u].size(); i++) {
                ll v = vec[u][i].first, val = vec[u][i].second;
                if (!vis[v] && dis[v] > dis[u] + val) {
                    dis[v] = dis[u] + val;
                    q.push({ dis[v], v });
                }
            }
        }
        if (dis[en] == inf)
            return 0;
        memset(vis, 0, sizeof(vis));
        queue<ll> que;
        que.push(en);
        memset(head, -1, sizeof(head));
        tot = 0;
        while (!que.empty()) {
            ll u = que.front();
            que.pop();
            if (vis[u])
                continue;
            vis[u] = 1;
            for (ll i = 0; i < vec2[u].size(); i++) {
                ll v = vec2[u][i].first, val = vec2[u][i].second;
                if (dis[v] + val == dis[u]) {
                    que.push(v);
                    add(v, u, val);
                    add(u, v, 0);
                }
            }
        }
        return 1;
    }
    ll s, t, cur[N], dep[N];
    ll bfs()
    {
        queue<ll> q;
        q.push(s);
        memset(dep, -1, sizeof(dep));
        dep[s] = 0;
        memcpy(cur, head, sizeof(head));
        while (!q.empty()) {
            ll now = q.front();
            q.pop();
            for (ll i = head[now]; i != -1; i = edge[i].next) {
                ll v = edge[i].to, val = edge[i].val;
                if (edge[i].val && dep[v] == -1) {
                    dep[v] = dep[now] + 1;
                    q.push(v);
                }
            }
        }
        return dep[t] != -1;
    }
    
    ll dfs(ll u, ll flow)
    {
        if (u == t) {
            return flow;
        }
        ll rel = flow;
        for (ll i = cur[u]; i != -1; i = edge[i].next) {
            if (!rel)
                break;
            cur[u] = i;
            ll v = edge[i].to, val = edge[i].val;
            if (val > 0 && dep[v] == dep[u] + 1) {
                ll tmp = dfs(v, min(val, rel));
                edge[i].val -= tmp;
                edge[i ^ 1].val += tmp;
                rel -= tmp;
            }
        }
        return flow - rel;
    }
    
    ll dinic()
    {
        ll ans = 0;
        while (bfs()) {
            ans += dfs(s, inf);
        }
        return ans;
    }
    int main()
    {
        ll T;
        scanf("%lld", &T);
        while (T--) {
            ll n, m;
            scanf("%lld%lld", &n, &m);
            for (int i = 1; i <= n; i++) {
                vec[i].clear(), vec2[i].clear();
            }
            for (ll i = 1; i <= m; i++) {
                ll u, v, val;
                scanf("%lld%lld%lld", &u, &v, &val);
                vec[u].pb({ v, val }), vec2[v].pb({ u, val });
            }
            dijkstra(1, n);
            s = 1, t = n;
            printf("%lld
    ", dinic());
        }
        return 0;
    }
    
  • 相关阅读:
    类的设计问题
    php数组存在重复的相反元素,去重复
    常用JS验证函数总结
    python常用模块
    re 模块
    logging 模块
    configparser模块
    python 文件处理
    第15章-输入/输出 --- 理解Java的IO流
    第10章-验证框架 --- 验证器类型
  • 原文地址:https://www.cnblogs.com/valk3/p/13863242.html
Copyright © 2011-2022 走看看