HDU 6582 Path BZOJ 1266 上学路线route 网络流 最短路

给出一个图, 问从起点到终点, 问去掉一些边使得最短路增大, 求最少的花费是多少(6582是边长, 1266是给定的).

另外, 6582是有向边, 1266是无向边.

这个题可以分解成两部分:

Ⅰ求出最短路所有路径上的边

Ⅱ在Ⅰ上新建一个图, 跑网络流最小割.

最小割: 就是把起点和汇点割开的最小花费.

这样, 就是花费最少的代价, 把所有的最短路径割断, 进而增大了最短路.

Ⅰ就是检查每一条边u→v, s→u+len[u→v]是否=s→v, 如果是的话, 它就可能是最短路上的点(是最短路上的点, 但这个最短路可能不是到终点的).

6582

#include<bits/stdc++.h>

using namespace std;

void debug_out() { cerr << '\n'; }

template<typename T, typename ...R>
void debug_out(const T &f, const R &...r) {
    cerr << f << " ";
    debug_out(r...);
}

#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
typedef long long ll;
typedef pair<int, ll> pil;

inline ll read() {
    ll x = 0;
    int f = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x = f ? -x : x;
}

inline void write(ll x) {
    if (x == 0) {
        putchar('0'), putchar('\n');
        return;
    }
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    static char s[23];
    int l = 0;
    while (x != 0)s[l++] = x % 10 + 48, x /= 10;
    while (l)putchar(s[--l]);
    putchar('\n');
}

int lowbit(int x) { return x & (-x); }

template<class T>
T big(const T &a1, const T &a2) { return a1 > a2 ? a1 : a2; }

template<typename T, typename ...R>
T big(const T &f, const R &...r) { return big(f, big(r...)); }

template<class T>
T sml(const T &a1, const T &a2) { return a1 < a2 ? a1 : a2; }

template<typename T, typename ...R>
T sml(const T &f, const R &...r) { return sml(f, sml(r...)); }

const int M = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;

int _;

struct edge {
    int u, v, nxt;
    ll w;
} edgesSP[M];

int ei;
int head[M];
ll disFromS[M];
ll disFromT[M];
int s, t;
int n;
int vis[M];

namespace SP {
    void init() {
        ei = 0;
        memset(head, -1, sizeof(head));
    }


    void addedge(int u, int v, ll w) {
        edgesSP[ei].u = u, edgesSP[ei].v = v, edgesSP[ei].w = w, edgesSP[ei].nxt = head[u];
        head[u] = ei++;
    }


    void shortPath(int s, ll *dis) {
        memset(vis, 0, sizeof(vis));
        fill(dis, dis + n + 1, INF);
        dis[s] = 0;
        queue<pil> q;
        q.push(make_pair(s, 0));
        while (!q.empty()) {
            pil now = q.front();
            q.pop();
            int d = now.second;
            int u = now.first;
//            debug(u, d);
            if (vis[u])continue;
            vis[u] = 1;
            for (int i = head[u]; i != -1; i = edgesSP[i].nxt) {
                int v = edgesSP[i].v;
                if (dis[v] > dis[u] + edgesSP[i].w) {
                    dis[v] = dis[u] + edgesSP[i].w;
                    q.push(make_pair(v, dis[v]));
                }
            }
        }
    }

}
namespace DINIC {
    const int MAXN = 1e5 + 5;//点数的最大值
    const int MAXM = 1e5 + 5;//边数的最大值
    struct Edge {
        int to, next;
        ll cap, flow;
    } edge[MAXM * 2]; //注意是 MAXM
    int tol;
    int head[MAXN];

    void init() {
        tol = 2;
        memset(head, -1, sizeof(head));
    }

    void addedge(int u, int v, ll w, ll rw = 0) {
        edge[tol].to = v;
        edge[tol].cap = w;
        edge[tol].flow = 0;
        edge[tol].next = head[u];
        head[u] = tol++;
        edge[tol].to = u;
        edge[tol].cap = rw;//无向图不要建4次边, 把反向边流量也设成w
        edge[tol].flow = 0;
        edge[tol].next = head[v];
        head[v] = tol++;
    }

    int Q[MAXN];
    int dep[MAXN], cur[MAXN], sta[MAXN];

    bool bfs(int s, int t, int n) {//bfs分层
        int front = 0, tail = 0;
        memset(dep, -1, sizeof(dep[0]) * (n + 1));
        dep[s] = 0;
        Q[tail++] = s;
        while (front < tail) {
            int u = Q[front++];
            for (int i = head[u]; i != -1; i = edge[i].next) {
                int v = edge[i].to;
                if (edge[i].cap > edge[i].flow && dep[v] == -1) {
                    dep[v] = dep[u] + 1;
                    if (v == t)
                        return true;
                    Q[tail++] = v;
                }
            }
        }
        return false;
    }

    ll dinic(int s, int t, int n) {
        ll maxflow = 0;
        while (bfs(s, t, n)) {
            for (int i = 1; i <= n; i++)//下标从0开始/从1开始
                cur[i] = head[i];
            int u = s, tail = 0;
            while (cur[s] != -1)///栈模拟dfs
            {
//            printf("%d %d %lld\n",s,cur[s],maxflow);
                if (u == t) {//走到了t点
                    ll tp = INF;
                    for (int i = tail - 1; i >= 0; i--)
                        tp = std::min(tp, edge[sta[i]].cap - edge[sta[i]].flow);
                    maxflow += tp;
                    for (int i = tail - 1; i >= 0; i--) {
                        edge[sta[i]].flow += tp;
                        edge[sta[i] ^ 1].flow -= tp;
                        if (edge[sta[i]].cap - edge[sta[i]].flow == 0)
                            tail = i;
                    }
                    u = edge[sta[tail] ^ 1].to;
                } else if (cur[u] != -1
                           && edge[cur[u]].cap > edge[cur[u]].flow
                           && dep[u] + 1 == dep[edge[cur[u]].to]) {//如果还没走到t, 并且还能走,那就继续dfs
                    sta[tail++] = cur[u];
                    u = edge[cur[u]].to;
                } else {//如果走不了了, 那就返回到上一层
                    while (u != s && cur[u] == -1)
                        u = edge[sta[--tail] ^ 1].to;
                    cur[u] = edge[cur[u]].next;
                }
            }
        }
        return maxflow;
    }
}


struct node {
    int u, v;
    ll w;
} edgeOnGraphBF[M];


int main() {
    _ = read();
    while (_--) {
        n = read();
        int m;
        m = read();
        SP::init();
        for (int i = 0; i < m; ++i) {
            int u = read(), v = read();
            ll w = read();
            edgeOnGraphBF[i] = node{u, v, w};
//            edgeOnGraphBF[i] = node{v, u, w};
            SP::addedge(u, v, w);
//            SP::addedge(v, u, w);
        }
        SP::shortPath(1, disFromS);
//        debug(disFromS[n]);
        SP::init();
        for (int i = 0; i < m; ++i) {
            int u = edgeOnGraphBF[i].v, v = edgeOnGraphBF[i].u;
            ll w = edgeOnGraphBF[i].w;
            SP::addedge(u, v, w);
        }
        SP::shortPath(n, disFromT);
//        debug(disFromT[1]);
        queue<node> q;//最短路上的边, 要拿来跑最大流
        for (int i = 0; i < m; ++i) {
            node now = edgeOnGraphBF[i];
            if (disFromS[now.u] + now.w == disFromS[now.v])
//            if (disFromS[now.u] + now.w + disFromT[now.v] == disFromT[1])
                q.push(now);
        }
        if (q.empty()) {
            printf("0\n");
            continue;
        }
        DINIC::init();
        while (!q.empty()) {
            DINIC::addedge(q.front().u, q.front().v, q.front().w);
            q.pop();
        }
        printf("%lld\n", DINIC::dinic(1, n, n));
    }
    return 0;
}

1266:

/**************************************************************
    Problem: 1266
    User: swqeaaa
    Language: C++
    Result: Accepted
    Time:340 ms
    Memory:36144 kb
****************************************************************/
 
#include<bits/stdc++.h>
 
using namespace std;
 
void debug_out() { cerr << '\n'; }
 
template<typename T, typename ...R>
void debug_out(const T &f, const R &...r) {
    cerr << f << " ";
    debug_out(r...);
}
 
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<int, ll> pil;
 
inline ll read() {
    ll x = 0;
    int f = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x = f ? -x : x;
}
 
inline void write(ll x) {
    if (x == 0) {
        putchar('0'), putchar('\n');
        return;
    }
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    static char s[23];
    int l = 0;
    while (x != 0)s[l++] = x % 10 + 48, x /= 10;
    while (l)putchar(s[--l]);
    putchar('\n');
}
 
int lowbit(int x) { return x & (-x); }
 
template<class T>
T big(const T &a1, const T &a2) { return a1 > a2 ? a1 : a2; }
 
template<typename T, typename ...R>
T big(const T &f, const R &...r) { return big(f, big(r...)); }
 
template<class T>
T sml(const T &a1, const T &a2) { return a1 < a2 ? a1 : a2; }
 
template<typename T, typename ...R>
T sml(const T &f, const R &...r) { return sml(f, sml(r...)); }
 
const int M = 212345;// 2e5+5
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;// 1e9+7
 
int n;
 
 
// update on 2019/7/25
namespace SP {
    //点数n要开全局
    //记得初始化init, 以及是否为双向边
    const int MAXN = M;//点数的最大值
    const int MAXM = M;//边数的最大值
    struct edge {
        int u, v, nxt;
        ll w;
        ll c;
    } edgesSP[/*边数*/MAXM * 2];
    int ei;
    int head[MAXN];
    ll dis[MAXN];
    int vis[MAXN];
 
    void init() {
        ei = 0;
        memset(head, -1, sizeof(head));
    }
 
    void addedge(int u, int v, ll w, ll c) {
        edgesSP[ei].u = u, edgesSP[ei].v = v, edgesSP[ei].w = w, edgesSP[ei].c = c, edgesSP[ei].nxt = head[u];
        head[u] = ei++;
    }
 
    struct qnode {
        int first;
        ll second;
 
        bool operator<(const qnode a) const {
            return second > a.second;
        }
    };
 
    void shortPath(int s) {
        memset(vis, 0, sizeof(vis));
        fill(dis, dis + M, INF);
        dis[s] = 0;
//        queue<pil> q;
        priority_queue<qnode> q;
        q.push({s, 0});
        while (!q.empty()) {
            qnode now = q.top();
            q.pop();
            ll d = now.second;//dij里面这个没用, 是prim求生成树用的.
            int u = now.first;
            if (vis[u])continue;
            vis[u] = 1;
            for (int i = head[u]; i != -1; i = edgesSP[i].nxt) {
                int v = edgesSP[i].v;
                if (dis[v] > dis[u] + edgesSP[i].w) {
                    dis[v] = dis[u] + edgesSP[i].w;
                    q.push({v, dis[v]});
                }
            }
        }
    }
}
 
namespace DINIC {
    //记得初始化init, 以及是否为双向边
    const int MAXN = 3e5 + 5;//点数的最大值
    const int MAXM = 3e5 + 5;//边数的最大值
    struct Edge {
        int to, next;
        ll cap, flow;
    } edge[MAXM * 2]; //注意是 MAXM
    int tol;
    int head[MAXN];
 
    void init() {
        tol = 2;
        memset(head, -1, sizeof(head));
    }
 
    void addedge(int u, int v, ll w, ll rw = 0) {
        edge[tol].to = v;
        edge[tol].cap = w;
        edge[tol].flow = 0;
        edge[tol].next = head[u];
        head[u] = tol++;
        edge[tol].to = u;
        edge[tol].cap = rw;//无向图不要建4次边, 把反向边流量也设成w
//        edge[tol].cap = w;//无向图不要建4次边, 把反向边流量也设成w
        edge[tol].flow = 0;
        edge[tol].next = head[v];
        head[v] = tol++;
    }
 
    int Q[MAXN];
    int dep[MAXN], cur[MAXN], sta[MAXN];
 
    bool bfs(int s, int t, int n) {//bfs分层
        int front = 0, tail = 0;
        memset(dep, -1, sizeof(dep[0]) * (n + 1));
        dep[s] = 0;
        Q[tail++] = s;
        while (front < tail) {
            int u = Q[front++];
            for (int i = head[u]; i != -1; i = edge[i].next) {
                int v = edge[i].to;
                if (edge[i].cap > edge[i].flow && dep[v] == -1) {
                    dep[v] = dep[u] + 1;
                    if (v == t)
                        return true;
                    Q[tail++] = v;
                }
            }
        }
        return false;
    }
 
    int dinic(int s, int t, int n) {
        ll maxflow = 0;
        while (bfs(s, t, n)) {
            for (int i = 1; i <= n; i++)//下标从0开始/从1开始
                cur[i] = head[i];
            int u = s, tail = 0;
            while (cur[s] != -1)///栈模拟dfs
            {
//            printf("%d %d %lld\n",s,cur[s],maxflow);
                if (u == t) {//走到了t点
                    ll tp = INF;
                    for (int i = tail - 1; i >= 0; i--)
                        tp = std::min(tp, edge[sta[i]].cap - edge[sta[i]].flow);
                    maxflow += tp;
                    for (int i = tail - 1; i >= 0; i--) {
                        edge[sta[i]].flow += tp;
                        edge[sta[i] ^ 1].flow -= tp;
                        if (edge[sta[i]].cap - edge[sta[i]].flow == 0)
                            tail = i;
                    }
                    u = edge[sta[tail] ^ 1].to;
                } else if (cur[u] != -1
                           && edge[cur[u]].cap > edge[cur[u]].flow
                           && dep[u] + 1 == dep[edge[cur[u]].to]) {//如果还没走到t, 并且还能走,那就继续dfs
                    sta[tail++] = cur[u];
                    u = edge[cur[u]].to;
                } else {//如果走不了了, 那就返回到上一层
                    while (u != s && cur[u] == -1)
                        u = edge[sta[--tail] ^ 1].to;
                    cur[u] = edge[cur[u]].next;
                }
            }
        }
        return maxflow;
    }
}
 
void init() {
    n = read();
    int m = read();
    SP::init();
    for (int i = 0; i < m; ++i) {
        int u = read(), v = read();
        ll t = read(), c = read();
        SP::addedge(u, v, t, c);
        SP::addedge(v, u, t, c);
    }
    SP::shortPath(1);
    write(SP::dis[n]);
    DINIC::init();
    for (int i = 1; i <= n; i++) {
//        debug(i);
        for (int j = SP::head[i]; j != -1; j = SP::edgesSP[j].nxt) {
//            debug(j);
            if (SP::dis[i] + SP::edgesSP[j].w == SP::dis[SP::edgesSP[j].v]) {
                DINIC::addedge(i, SP::edgesSP[j].v, SP::edgesSP[j].c);
            }
        }
    }
    write(DINIC::dinic(1, n, n));
}
 
void solve() {
 
}
 
int main() {
 
    init();
 
    solve();
 
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值