zoukankan      html  css  js  c++  java
  • SCU 4584 tarjan+最大权闭合子图

    把每个点的点权当做是W[i]-V[i] 题目一眼是最大权闭合子图 但是可能会有重边自环和环 需要先搞成简单图 再tarjan缩点 缩点后就是裸的最大权闭合子图

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN = 105000;
    const int MAXM = 1000005;
    const ll  INF = 200000000050000LL;
    int Head[MAXN], cur[MAXN], lev[MAXN], to[MAXM << 1], nxt[MAXM << 1], ed, S, T;
    ll f[MAXM << 1];
    inline void addedge2(int u, int v) {
            to[++ed] = v;
            nxt[ed] = Head[u];
            Head[u] = ed;
            return;
    }
    inline void addedge(int u, int v, ll cap) {
            to[++ed] = v;
            nxt[ed] = Head[u];
            Head[u] = ed;
            f[ed] = cap;
            to[++ed] = u;
            nxt[ed] = Head[v];
            Head[v] = ed;
            f[ed] = 0;
            return;
    }
    inline bool BFS() {
            int u;
            memset(lev, -1, sizeof(lev));
            queue<int>q;
            lev[S] = 0;
            q.push(S);
            while (q.size()) {
                    u = q.front();
                    q.pop();
                    for (int i = Head[u]; i; i = nxt[i])
                            if (f[i] && lev[to[i]] == -1) {
                                    lev[to[i]] = lev[u] + 1;
                                    q.push(to[i]);
                                    /*
                                    if (to[i] == T)
                                    {
                                            return 1;
                                    }
                                    magic one way optimize
                                    */
                            }
            }
            memcpy(cur, Head, sizeof Head);
            return lev[T] != -1;
    }
    inline ll DFS(int u, ll maxf) {
            if (u == T || !maxf) {
                    return maxf;
            }
            ll cnt = 0, tem;
            for (int &i = cur[u]; i; i = nxt[i])
                    if (f[i] && lev[to[i]] == lev[u] + 1) {
                            tem = DFS(to[i], min(maxf, f[i]));
                            maxf -= tem;
                            f[i] -= tem;
                            f[i ^ 1] += tem;
                            cnt += tem;
                            if (!maxf) {
                                    break;
                            }
                    }
            if (!cnt) {
                    lev[u] = -1;
            }
            return cnt;
    }
    ll Dinic() {
            ll ans = 0;
            while (BFS()) {
                    ans += DFS(S, INF);
            }
            return ans;
    }
    void init(int SS, int TT) {
            ed = 1;
            S = SS;
            T = TT;
            return;
    }
    //Directed tarjan(without repeat edge)
    int deep, colorsum = 0;
    int top;/*sta目前的大小*/
    int dfn[MAXN], color[MAXN], low[MAXN];
    int sta[MAXN];//存着当前所有可能能构成强连通分量的点
    bool visit[MAXN];//表示一个点目前是否在sta中
    int cnt[MAXN];//各个强连通分量中含点的数目
    ll valsum[MAXN];
    void tarjan(int x) {
            dfn[x] = ++deep;
            low[x] = deep;
            visit[x] = 1;
            sta[++top] = x;
            for (int i = Head[x]; i; i = nxt[i]) {
                    int v = to[i];
                    if (!dfn[v]) {
                            tarjan(v);
                            low[x] = min(low[x], low[v]);
                    } else {
                            if (visit[v]) {
                                    low[x] = min(low[x], low[v]);
                            }
                    }
            }
            if (dfn[x] == low[x]) {
                    color[x] = ++colorsum;
                    visit[x] = 0;
                    while (sta[top] != x) {
                            color[sta[top]] = colorsum;
                            visit[sta[top--]] = 0;
                    }
                    top--;
            }
    }
    ll w[MAXN];
    pair<int, int> Edge[MAXM];
    map<pair<int, int>, int> mp;
    int main() {
            int n, m, x;
            int u, v, c;
            int TNT;
            scanf("%d", &TNT);
            while (TNT--) {
                    mp.clear();
                    scanf("%d %d", &n, &m);
                    top = colorsum = 0;
                    for (int i = 0; i <= n + 1; i++) {
                            visit[i] = dfn[i] = low[i] = cnt[i] = color[i] = Head[i] = 0;
                            valsum[i] = 0;
                    }
                    ed = 1;
                    for (int i = 1; i <= n; i++) {
                            scanf("%lld", &w[i]);
                    }
                    for (int i = 1; i <= n; i++) {
                            scanf("%d", &x);
                            w[i] -= x;
                    }
                    for (int i = 1; i <= m; i++) {
                            scanf("%d %d", &u, &v);
                            if (u == v || mp[make_pair(u, v)]) {
                                    Edge[i].first = u, Edge[i].second = u;
                                    continue;
                            }
                            mp[make_pair(u, v)] = 1;
                            Edge[i].first = u, Edge[i].second = v;
                            addedge2(u, v);
                    }
                    for (int i = 1; i <= n; i++) {
                            if (!dfn[i]) {
                                    tarjan(i);
                            }
                    }
                    for (int i = 1; i <= n; i++) {
                            valsum[color[i]] += w[i];
                    }
                    init(0, n + 1);
                    for (int i = 0; i <= n + 1; i++) {
                            Head[i] = 0;
                    }
                    ll anser = 0;
                    for (int i = 1; i <= colorsum; i++) {
                            if (valsum[i] > 0) {
                                    anser += valsum[i];
                                    addedge(S, i, valsum[i]);
                            } else if (valsum[i] < 0) {
                                    addedge(i, T, -valsum[i]);
                            }
                    }
                    for (int i = 1; i <= m; i++) {
                            u = Edge[i].first;
                            v = Edge[i].second;
                            if (color[u] == color[v]) {
                                    continue;
                            }
                            addedge(color[u], color[v], INF);
                    }
                    cout << anser - Dinic() << endl;
            }
            return 0;
    }
    View Code
  • 相关阅读:
    关于VS2010出现“此方法显式使用的 CAS 策略已被 .NET Framework 弃用... ...请使用 NetFx40_LegacySecurityPolicy 配置开关”解决办法
    数据挖掘---Pandas的学习
    数据挖掘---Numpy的学习
    数据挖掘---Matplotib的学习
    AI学习---数据IO操作&神经网络基础
    AI学习---基于TensorFlow的案例[实现线性回归的训练]
    AI学习---卷积神经网络
    AI学习---数据读取&神经网络
    AI学习---TensorFlow框架介绍[图+会话+张量+变量OP+API]
    AI学习---深度学习&TensorFlow安装
  • 原文地址:https://www.cnblogs.com/Aragaki/p/10629691.html
Copyright © 2011-2022 走看看