上下界网络流

无源无汇有容量上下界网络的可行流

  网络不仅无源无汇,而且每条边除了有容量上界c之外,还有一个容量下界b,所有结点都应满足“入流=出流”这个流量平衡条件,要求出满足这些流量平衡条件的可行流。
  这时候就有一个结论:如果可行流存在,则原图一定是强连通的。因此可以先检查原图如果不是强连通的,则必然不存在可行流。
  附加源点s和汇点t,把每条边 u → v u\rightarrow v uv拆成3条,再进行合并,如下图所示。求出最大流 f l o w flow flow后,若 f l o w = ∑ b i flow=\sum b_i flow=bi则可行流存在。如果要输出每条边的实际流量只用将新图边 u → v u\rightarrow v uv的的流量加上下界b即可。
无源无汇有容量上下界网络的可行流求法
模板题 zoj-2314 Reactor Cooling

#include <iostream>
#include <cstring>
using namespace std;

#define INF 0x7f7f7f7f
#define N 202
struct edge {int u, v, cap, flow;} e[N*N];
int g[N][N], q[N], p[N], d[N], cur[N], num[N], cnt[N], cs[N], ct[N], h[N*N>>1], b[N*N>>1], c, m, n, f; bool vis[N];

void add_edge(int u, int v, int cap) {
    e[c].u = u; e[c].v = v; e[c].cap = cap; e[c].flow = 0; g[u][cnt[u]++] = c++;
    e[c].u = v; e[c].v = u; e[c].cap = 0; e[c].flow = 0; g[v][cnt[v]++] = c++;
}

bool bfs(int s, int t) {
    memset(vis, 0, sizeof(vis)); memset(d, 0, sizeof(d)); q[0] = t; d[t] = 0; vis[t] = true;
    int head = 0, tail = 1;
    while (head < tail) {
        int v = q[head++];
        for (int i=0; i<cnt[v]; ++i) {
            const edge& ee = e[g[v][i]^1];
            if (!vis[ee.u] && ee.cap > ee.flow) vis[ee.u] = true, d[ee.u] = d[v] + 1, q[tail++] = ee.u;
        }
    }
    return vis[s];
}

int max_flow(int s, int t) {
    int flow = 0, u = s;
    if (!bfs(s, t)) return 0;
    memset(num, 0, sizeof(num)); memset(cur, 0, sizeof(cur));
    for (int i=0; i<=t; ++i) ++num[d[i]];
    while (d[s] <= t) {
        if (u == t) {
            int a = INF;
            for (int v=t; v!=s; v = e[p[v]].u) a = min(a, e[p[v]].cap - e[p[v]].flow);
            for (int v=t; v!=s; v = e[p[v]].u) e[p[v]].flow += a, e[p[v]^1].flow -= a;
            flow += a; u = s;
        }
        int ok = 0;
        for (int i=cur[u]; i<cnt[u]; ++i) {
            const edge& ee = e[g[u][i]];
            if (ee.cap > ee.flow && d[u] == d[ee.v] + 1) {
                ok = 1; p[ee.v] = g[u][i]; cur[u] = i; u = ee.v;
                break;
            }
        }
        if (!ok) {
            int m = t;
            for (int i=0; i<cnt[u]; ++i) {
                const edge& ee = e[g[u][i]];
                if (ee.cap > ee.flow) m = min(m, d[ee.v]);
            }
            if (--num[d[u]] == 0) break;
            ++num[d[u] = m + 1]; cur[u] = 0;
            if (u != s) u = e[p[u]].u;
        }
    }
    return flow;
}

void solve() {
    cin >> n >> m; memset(cnt, c = f = 0, sizeof(cnt)); memset(cs, 0, sizeof(cs)); memset(ct, 0, sizeof(ct));
    int s = 0, t = n+1;
    for (int i=0; i<m; ++i) {
        int u, v, s; cin >> u >> v >> b[i] >> s;
        f += b[i]; cs[v] += b[i]; ct[u] += b[i]; h[i] = c; add_edge(u, v, s-b[i]);
    }
    for (int i=1; i<=n; ++i) {
        if (cs[i]) add_edge(s, i, cs[i]);
        if (ct[i]) add_edge(i, t, ct[i]);
    }
    if (max_flow(s, t) == f) {
        cout << "YES" << endl;
        for (int i=0; i<m; ++i) cout << e[h[i]].flow + b[i] << endl;
    } else cout << "NO" << endl;
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int t; cin >> t;
    while (t--) {
        solve();
        if (t) cout << endl;
    }
    return 0;
}

  需要稍加分析的题目 HDU-4940 Destroy Transportation system
  题意:给出一个有向强连通图,每条边有两个值分别是删除该边的代价D和把该边建成无向边的代价B(建立无向边的前提是删除该边)问是否存在一个顶点的非空真子集S和其补集T,破坏所有S集合到T集合的边代价和是X,然后边建T到S的边为无向边代价和是Y,满足Y<X;满足输出unhappy,否则输出happy。
  分析:原来每条边转化成下界为D上界为D+B,判断是否存在可行流即可。如果存在可行流,那么说明对于任意的S集合流出的肯定等于流入的,流出的计算的X肯定小于等于这个流量(X是下界之和), 计算出来的Y (上界之和)肯定大于等于这个流量,肯定满足X<=Y。

有源有汇有容量上下界网络的可行流

  这时候往往汇点和源点无边相连(原图不是强连通的),需要连一条汇点到源点且容量上下界为 [ 0 , i n f ] [0,inf] [0,inf]的边,就变成了无源无汇有容量上下界网络的可行流。
  例题:poj2396 Budget
  本题首先可以用和UVa11082 Matrix Decompressing一样的办法求,只需要先将每个矩阵元素减掉下限(同时行列和也减)之后就和UVa11082一样求最大流即可,最后输出答案时需要加回减掉的下限。
  也可以用有源有汇有容量上下界网络的可行流来处理,建图方法首先和UVa11082一样,然后连一条汇点到源点且容量上下界均为矩阵所有元素之和的边。

#include <iostream>
#include <cstring>
using namespace std;

#define INF 0x7f7f7f7f
#define M 202
#define N 22
#define T 224
struct edge {int u, v, cap, flow;} e[M*N<<1];
int g[T][M], l[M][N], u[M][N], q[T], p[T], d[T], cur[T], num[T], cnt[T], cs[T], ct[T], c, m, n; bool vis[T];

void add_edge(int u, int v, int cap) {
    e[c].u = u; e[c].v = v; e[c].cap = cap; e[c].flow = 0; g[u][cnt[u]++] = c++;
    e[c].u = v; e[c].v = u; e[c].cap = 0; e[c].flow = 0; g[v][cnt[v]++] = c++;
}

bool bfs(int s, int t) {
    memset(vis, 0, sizeof(vis)); memset(d, 0, sizeof(d)); q[0] = t; d[t] = 0; vis[t] = true;
    int head = 0, tail = 1;
    while (head < tail) {
        int v = q[head++];
        for (int i=0; i<cnt[v]; ++i) {
            const edge& ee = e[g[v][i]^1];
            if (!vis[ee.u] && ee.cap > ee.flow) vis[ee.u] = true, d[ee.u] = d[v] + 1, q[tail++] = ee.u;
        }
    }
    return vis[s];
}

bool upd(char s, int v, int r, int c) {
    if (s == '=') {
        if (l[r][c] > v || u[r][c] < v) return false;
        l[r][c] = u[r][c] = v;
    } else if (s == '>') {
        if (u[r][c] < ++v) return false;
        l[r][c] = max(l[r][c], v);
    } else {
        if (l[r][c] > --v) return false;
        u[r][c] = min(u[r][c], v);
    }
    return true;
}

bool check_lu() {
    int k; bool ok = true; cin >> k;
    while (k--) {
        int r, c, v; char s; cin >> r >> c >> s >> v;
        if (r) {
            if (c) {
                if (!upd(s, v, r, c)) ok = false;
            } else for (c=1; c<=n; ++c) if (!upd(s, v, r, c)) {
                ok = false; break;
            }
        } else if (c) {
            for (r=1; r<=m; ++r) if (!upd(s, v, r, c)) {
                ok = false; break;
            }
        } else for (r=1; r<=m; ++r) for (c=1; c<=n; ++c) if (!upd(s, v, r, c)) {
            ok = false; break;
        }
    }
    return ok;
}

void solve() {
    cin >> m >> n; memset(l, 0, sizeof(l)); memset(u, 127, sizeof(u)); memset(cnt, c = 0, sizeof(cnt));
    int s = 0, t = m+n+1, f = 0, f2 = 0; memset(cs, 0, sizeof(cs)); memset(ct, 0, sizeof(ct));
    for (int i=1, x; i<=m; ++i) cin >> x, f += x, add_edge(s, i, x);
    for (int i=1, x; i<=n; ++i) cin >> x, f2 += x, add_edge(m+i, t, x);
    if (!check_lu() || f != f2) {
        cout << "IMPOSSIBLE" << endl;
        return;
    }
    add_edge(t+1, s, f); add_edge(t, t+2, f); s = t+1; t = s+1;
    for (int r=1; r<=m; ++r) for (int c=1; c<=n; ++c) {
        f += l[r][c]; cs[m+c] += l[r][c]; ct[r] += l[r][c];
        if (u[r][c] > l[r][c]) add_edge(r, m+c, u[r][c] - l[r][c]);
    }
    for (int r=1; r<=m; ++r) if (ct[r]) add_edge(r, t, ct[r]);
    for (int c=1; c<=n; ++c) if (cs[m+c]) add_edge(s, m+c, cs[m+c]);
    if (!bfs(s, t)) {
        if (f) cout << "IMPOSSIBLE" << endl;
        else for (int r=1; r<=m; ++r) for (int c=1; c<=n; ++c) cout << l[r][c], cout << (c<n ? ' ' : '\n');
        return;
    }
    memset(num, 0, sizeof(num)); memset(cur, 0, sizeof(cur));
    for (int i=0; i<=t; ++i) ++num[d[i]];
    for (int u = s; d[s] <= t;) {
        if (u == t) {
            int a = INF;
            for (int v=t; v!=s; v = e[p[v]].u) a = min(a, e[p[v]].cap - e[p[v]].flow);
            for (int v=t; v!=s; v = e[p[v]].u) e[p[v]].flow += a, e[p[v]^1].flow -= a;
            f -= a; u = s;
        }
        bool ok = false;
        for (int i=cur[u]; i<cnt[u]; ++i) {
            const edge& ee = e[g[u][i]];
            if (ee.cap > ee.flow && d[u] == d[ee.v] + 1) {
                ok = true; p[ee.v] = g[u][i]; cur[u] = i; u = ee.v;
                break;
            }
        }
        if (!ok) {
            int m = t;
            for (int i=0; i<cnt[u]; ++i) {
                const edge& ee = e[g[u][i]];
                if (ee.cap > ee.flow) m = min(m, d[ee.v]);
            }
            if (--num[d[u]] == 0) break;
            ++num[d[u] = m + 1]; cur[u] = 0;
            if (u != s) u = e[p[u]].u;
        }
    }
    if (!f) {
        for (int i=1; i<=m; ++i) for (int j=0; j<cnt[i]; ++j) {
            const edge& ee = e[g[i][j]];
            if (ee.v > m && ee.v <= m+n) l[i][ee.v-m] += ee.flow;
        }
        for (int r=1; r<=m; ++r) for (int c=1; c<=n; ++c) cout << l[r][c], cout << (c<n ? ' ' : '\n');
    } else cout << "IMPOSSIBLE" << endl;
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int t; cin >> t;
    while (t--) {
        solve();
        if (t) cout << endl;
    }
    return 0;
}

有源有汇有容量上下界网络的最大流

  先求有源有汇有容量上下界网络的可行流(可行流不存在则无解),再在残量网络上求一次源点到汇点的最大流即可。
  模板题 zoj-3229 Shoot the Bullet
  题意:多组数据,读到文件结束。对于每一组数据,第一行为正整数 n , m n,m n,m表示 n n n天, m m m个少女。接下来一行, m m m个正整数 G 1 , G 2 . . . G m G_1,G_2...G_m G1,G2...Gm分别表示每个少女总共至少要拍的照片张数。接下来 n n n组,每一组第一行有两个整数 C i , D i C_i,D_i Ci,Di,表示这一天有 C i C_i Ci个少女要拍照,这一天的照片总数不超过 D i D_i Di。接着有 C i C_i Ci行,每行三个整数 k , L k , R k k,L_k,R_k k,Lk,Rk,表示在这一天里 k k k号少女要拍的照片数目处于 [ L k , R k ] [L_k,R_k] [Lk,Rk]区间。(注意少女是从0开始编号的。)满足这些条件以后,所有天的照片总数越多越好。如果有解输出照片总数,并按顺序输出每一天的少女拍照数目,否则输出-1,每组答案后输出一空行。

#include <iostream>
#include <cstring>
using namespace std;

#define INF 0x7f7f7f7f
#define N 1369
struct edge {int u, v, cap, flow;} e[60*N];
int g[N][N], b[365][N], q[N], p[N], d[N], cur[N], num[N], cnt[N], cs[N], ct[N], c, m, n, f; bool vis[N];

void add_edge(int u, int v, int cap) {
    e[c].u = u; e[c].v = v; e[c].cap = cap; e[c].flow = 0; g[u][cnt[u]++] = c++;
    e[c].u = v; e[c].v = u; e[c].cap = 0; e[c].flow = 0; g[v][cnt[v]++] = c++;
}

bool bfs(int s, int t) {
    memset(vis, 0, sizeof(vis)); memset(d, 0, sizeof(d)); q[0] = t; d[t] = 0; vis[t] = true;
    int head = 0, tail = 1;
    while (head < tail) {
        int v = q[head++];
        for (int i=0; i<cnt[v]; ++i) {
            const edge& ee = e[g[v][i]^1];
            if (!vis[ee.u] && ee.cap > ee.flow) vis[ee.u] = true, d[ee.u] = d[v] + 1, q[tail++] = ee.u;
        }
    }
    return vis[s];
}

int max_flow(int s, int t, int n) {
    int flow = 0, u = s;
    if (!bfs(s, t)) return 0;
    memset(num, 0, sizeof(num)); memset(cur, 0, sizeof(cur));
    for (int i=0; i<n; ++i) ++num[d[i]];
    while (d[s] < n) {
        if (u == t) {
            int a = INF;
            for (int v=t; v!=s; v = e[p[v]].u) a = min(a, e[p[v]].cap - e[p[v]].flow);
            for (int v=t; v!=s; v = e[p[v]].u) e[p[v]].flow += a, e[p[v]^1].flow -= a;
            flow += a; u = s;
        }
        int ok = 0;
        for (int i=cur[u]; i<cnt[u]; ++i) {
            const edge& ee = e[g[u][i]];
            if (ee.cap > ee.flow && d[u] == d[ee.v] + 1) {
                ok = 1; p[ee.v] = g[u][i]; cur[u] = i; u = ee.v;
                break;
            }
        }
        if (!ok) {
            int m = n-1;
            for (int i=0; i<cnt[u]; ++i) {
                const edge& ee = e[g[u][i]];
                if (ee.cap > ee.flow) m = min(m, d[ee.v]);
            }
            if (--num[d[u]] == 0) break;
            ++num[d[u] = m + 1]; cur[u] = 0;
            if (u != s) u = e[p[u]].u;
        }
    }
    return flow;
}

void solve() {
    memset(cnt, c = f = 0, sizeof(cnt)); memset(cs, 0, sizeof(cs)); memset(ct, 0, sizeof(ct));
    int s = m+n, t = s+1;
    for (int i=0, x; i<m; ++i) cin >> x, f += x, cs[i] += x, ct[s] += x, add_edge(s, i, INF);
    for (int i=0; i<n; ++i) {
        int c, d; cin >> c >> d; add_edge(m+i, t, d);
        while (c--) {
            int k, l, r; cin >> k >> l >> r; f += l; cs[m+i] += l; ct[k] += l; b[i][k] = l; add_edge(k, m+i, r-l);
        }
    }
    add_edge(t, s, INF); s = t+1; t = s+1;
    for (int i=s-2; i>=0; --i) {
        if (cs[i]) add_edge(s, i, cs[i]);
        if (ct[i]) add_edge(i, t, ct[i]);
    }
    if (max_flow(s, t, t+1) == f) {
        cout << max_flow(s-2, t-2, t+1) << endl;
        for (int i=0; i<n; ++i) for (int j=0, k=cnt[m+i]; j<k; ++j) {
            const edge &ee = e[g[m+i][j]^1];
            if (ee.u < m) cout << b[i][ee.u] + ee.flow << endl;
        }
    } else cout << -1 << endl;
    cout << endl;
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    while (cin >> n >> m) solve();
    return 0;
}

有源有汇有容量上下界网络的最小流

  先求有源有汇有容量上下界网络的可行流(可行流不存在则无解),此时得到汇点连向源点的无限边的流量 f f f,删除此边(及其反向边)后在残量网络上求一次汇点到源点的最大流 f l o w flow flow f − f l o w f-flow fflow即是答案。
  模板题 HDU-3157 Crazy Circuits

#include <iostream>
#include <cstring>
using namespace std;

#define INF 0x7f7f7f7f
#define N 54
struct edge {int u, v, cap, flow;} e[24*N];
int g[N][N], q[N], p[N], d[N], cur[N], num[N], cnt[N], cs[N], ct[N], c, m, n, f; bool vis[N];

void add_edge(int u, int v, int cap) {
    e[c].u = u; e[c].v = v; e[c].cap = cap; e[c].flow = 0; g[u][cnt[u]++] = c++;
    e[c].u = v; e[c].v = u; e[c].cap = 0; e[c].flow = 0; g[v][cnt[v]++] = c++;
}

bool bfs(int s, int t) {
    memset(vis, 0, sizeof(vis)); memset(d, 0, sizeof(d)); q[0] = t; d[t] = 0; vis[t] = true;
    int head = 0, tail = 1;
    while (head < tail) {
        int v = q[head++];
        for (int i=0; i<cnt[v]; ++i) {
            const edge& ee = e[g[v][i]^1];
            if (!vis[ee.u] && ee.cap > ee.flow) vis[ee.u] = true, d[ee.u] = d[v] + 1, q[tail++] = ee.u;
        }
    }
    return vis[s];
}

int max_flow(int s, int t, int n) {
    int flow = 0, u = s;
    if (!bfs(s, t)) return 0;
    memset(num, 0, sizeof(num)); memset(cur, 0, sizeof(cur));
    for (int i=0; i<n; ++i) ++num[d[i]];
    while (d[s] < n) {
        if (u == t) {
            int a = INF;
            for (int v=t; v!=s; v = e[p[v]].u) a = min(a, e[p[v]].cap - e[p[v]].flow);
            for (int v=t; v!=s; v = e[p[v]].u) e[p[v]].flow += a, e[p[v]^1].flow -= a;
            flow += a; u = s;
        }
        int ok = 0;
        for (int i=cur[u]; i<cnt[u]; ++i) {
            const edge& ee = e[g[u][i]];
            if (ee.cap > ee.flow && d[u] == d[ee.v] + 1) {
                ok = 1; p[ee.v] = g[u][i]; cur[u] = i; u = ee.v;
                break;
            }
        }
        if (!ok) {
            int m = n-1;
            for (int i=0; i<cnt[u]; ++i) {
                const edge& ee = e[g[u][i]];
                if (ee.cap > ee.flow) m = min(m, d[ee.v]);
            }
            if (--num[d[u]] == 0) break;
            ++num[d[u] = m + 1]; cur[u] = 0;
            if (u != s) u = e[p[u]].u;
        }
    }
    return flow;
}

int read() {
    int x; char c; cin >> c;
    if (c == '+') return 0;
    if (c == '-') return n+1;
    cin.unget(); cin >> x;
    return x;
}

void solve() {
    memset(cnt, c = f = 0, sizeof(cnt)); memset(cs, 0, sizeof(cs)); memset(ct, 0, sizeof(ct));
    int s = 0, t = n+1;
    while (m--) {
        int u = read(), v = read(), i; cin >> i; add_edge(u, v, INF); cs[v] += i; ct[u] += i; f += i;
    }
    add_edge(t, s, INF); s = t+1; t = s+1;
    for (int i=s-1; i>=0; --i) {
        if (cs[i]) add_edge(s, i, cs[i]);
        if (ct[i]) add_edge(i, t, ct[i]);
    }
    if (max_flow(s, t, t+1) == f) {
        cout << INF - max_flow(s-1, 0, t+1) << endl;
    } else cout << "impossible" << endl;
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    while (cin >> n >> m && m) solve();
    return 0;
}

  模板题 LibreOJ-117

#include <iostream>
#include <cstring>
#include <vector>
using namespace std;

#define INF 0x7f7f7f7f
#define M 750024
#define N 50006
struct edge {int u, v, cap, flow;} e[M]; vector<int> g[N];
int q[N], p[N], d[N], cur[N], num[N], cs[N], ct[N], c, m, n, f; bool vis[N];

void add_edge(int u, int v, int cap) {
    e[c].u = u; e[c].v = v; e[c].cap = cap; e[c].flow = 0; g[u].push_back(c++);
    e[c].u = v; e[c].v = u; e[c].cap = 0; e[c].flow = 0; g[v].push_back(c++);
}

bool bfs(int s, int t) {
    memset(vis, 0, sizeof(vis)); memset(d, 0, sizeof(d)); q[0] = t; d[t] = 0; vis[t] = true;
    int head = 0, tail = 1;
    while (head < tail) {
        int v = q[head++];
        for (int i=0; i<g[v].size(); ++i) {
            const edge& ee = e[g[v][i]^1];
            if (!vis[ee.u] && ee.cap > ee.flow) vis[ee.u] = true, d[ee.u] = d[v] + 1, q[tail++] = ee.u;
        }
    }
    return vis[s];
}

int max_flow(int s, int t, int n) {
    int flow = 0, u = s;
    if (!bfs(s, t)) return 0;
    memset(num, 0, sizeof(num)); memset(cur, 0, sizeof(cur));
    for (int i=0; i<n; ++i) ++num[d[i]];
    while (d[s] < n) {
        if (u == t) {
            int a = INF;
            for (int v=t; v!=s; v = e[p[v]].u) a = min(a, e[p[v]].cap - e[p[v]].flow);
            for (int v=t; v!=s; v = e[p[v]].u) e[p[v]].flow += a, e[p[v]^1].flow -= a;
            flow += a; u = s;
        }
        int ok = 0;
        for (int i=cur[u]; i<g[u].size(); ++i) {
            const edge& ee = e[g[u][i]];
            if (ee.cap > ee.flow && d[u] == d[ee.v] + 1) {
                ok = 1; p[ee.v] = g[u][i]; cur[u] = i; u = ee.v;
                break;
            }
        }
        if (!ok) {
            int m = n-1;
            for (int i=0; i<g[u].size(); ++i) {
                const edge& ee = e[g[u][i]];
                if (ee.cap > ee.flow) m = min(m, d[ee.v]);
            }
            if (--num[d[u]] == 0) break;
            ++num[d[u] = m + 1]; cur[u] = 0;
            if (u != s) u = e[p[u]].u;
        }
    }
    return flow;
}

void solve() {
    memset(cs, c = f = 0, sizeof(cs)); memset(ct, 0, sizeof(ct));
    int s, t, x; cin >> s >> t;
    for (int i=n+1; i>=0; --i) g[i].clear();
    while (m--) {
        int u, v, l, r; cin >> u >> v >> l >> r; cs[v] += l; ct[u] += l; f += l;
        if (l < r) add_edge(u, v, r-l);
    }
    x = c; add_edge(t, s, INF);
    for (int i=1; i<=n; ++i) {
        if (cs[i]) add_edge(0, i, cs[i]);
        if (ct[i]) add_edge(i, n+1, ct[i]);
    }
    if (max_flow(0, n+1, n+2) == f) {
        int ans = e[x].flow; e[x].cap = e[x].flow = e[x^1].flow = 0;
        cout << ans - max_flow(t, s, n+2) << endl;
    } else cout << "please go home to sleep" << endl;
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    while (cin >> n >> m) solve();
    return 0;
}

  UVa1440/LA4597 Inspection
  容量有下界的网络流求最小流,并且需要输出方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值