zoukankan      html  css  js  c++  java
  • HDU 3879 Base Station 最大权闭合图

    题目链接:点击打开链接

    题意:

    给定n个带权点m条无向带权边

    选一个子图。则这个子图的权值为 边权和-点权和

    求一个最大的权值


    把边也当成点。然后是最大权闭合图

    dinic:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    //点标 从0開始 F.Init(n) n=最大点标+10
    const int N = 200010;
    const int M = 500010;
    const int INF = ~0u >> 2;
    template<class T>
    struct Max_Flow {
        int n;
        int Q[N], sign;
        int head[N], level[N], cur[N], pre[N];
        int nxt[M], pnt[M], E;
        T cap[M];
        void Init(int n) {
            this->n = n;
            E = 0;
            std::fill(head, head + n, -1);
        }
        //有向rw 就= 0
        void add(int from, int to, T c, T rw) {
            pnt[E] = to;
            cap[E] = c;
            nxt[E] = head[from];
            head[from] = E++;
    
            pnt[E] = from;
            cap[E] = rw;
            nxt[E] = head[to];
            head[to] = E++;
        }
        bool Bfs(int s, int t) {
            sign = t;
            std::fill(level, level + n, -1);
            int *front = Q, *tail = Q;
            *tail++ = t; level[t] = 0;
            while(front < tail && level[s] == -1) {
                int u = *front++;
                for(int e = head[u]; e != -1; e = nxt[e]) {
                    if(cap[e ^ 1] > 0 && level[pnt[e]] < 0) {
                        level[pnt[e]] = level[u] + 1;
                        *tail ++ = pnt[e];
                    }
                }
            }
            return level[s] != -1;
        }
        void Push(int t, T &flow) {
            T mi = INF;
            int p = pre[t];
            for(int p = pre[t]; p != -1; p = pre[pnt[p ^ 1]]) {
                mi = std::min(mi, cap[p]);
            }
            for(int p = pre[t]; p != -1; p = pre[pnt[p ^ 1]]) {
                cap[p] -= mi;
                if(!cap[p]) {
                    sign = pnt[p ^ 1];
                }
                cap[p ^ 1] += mi;
            }
            flow += mi;
        }
        void Dfs(int u, int t, T &flow) {
            if(u == t) {
                Push(t, flow);
                return ;
            }
            for(int &e = cur[u]; e != -1; e = nxt[e]) {
                if(cap[e] > 0 && level[u] - 1 == level[pnt[e]]) {
                    pre[pnt[e]] = e;
                    Dfs(pnt[e], t, flow);
                    if(level[sign] > level[u]) {
                        return ;
                    }
                    sign = t;
                }
            }
        }
        T Dinic(int s, int t) {
            pre[s] = -1;
            T flow = 0;
            while(Bfs(s, t)) {
                std::copy(head, head + n, cur);
                Dfs(s, t, flow);
            }
            return flow;
        }
    };
    Max_Flow <int>F;
    int n, m;
    int work(){
        F.Init(n+m+10);
        int from = 0, to = n + m +1, A;
        for(int i = 1; i <= n; i++){
            scanf("%d", &A);
            F.add(i, to, A, 0);
        }
        int u, v, d, all = 0;
        for(int i = 1; i <= m; i++){
            scanf("%d %d %d", &u, &v, &d);
            all += d;
            F.add(from, n+i, d, 0);
            F.add(n+i, u, INF, 0);
            F.add(n+i, v, INF, 0);
        }
        return all - F.Dinic(from, to);
    }
    int main(){
        while(cin>>n>>m)
            cout<<work()<<endl;
        return 0;
    }
    


    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll int
    const int MAXN = 100010;//点数的最大值
    const int MAXM = 400010;//边数的最大值
    const int INF = 0x3f3f3f3f;
    struct Edge
    {
        int to,next,cap,flow;
    }edge[MAXM];//注意是MAXM
    int tol;
    int head[MAXN];
    int gap[MAXN],dep[MAXN],cur[MAXN];
    void add(int u,int v,int w,int 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; edge[tol].flow = 0;
        edge[tol].next = head[v]; head[v] = tol++;
    }
    int Q[MAXN];
    void BFS(int start,int end)
    {
        memset(dep,-1,sizeof(dep));
        memset(gap,0,sizeof(gap));
        gap[0] = 1;
        int front = 0, rear = 0;
        dep[end] = 0;
        Q[rear++] = end;
        while(front != rear)
        {
            int u = Q[front++];
            for(int i = head[u]; i != -1; i = edge[i].next)
            {
                int v = edge[i].to;
                if(dep[v] != -1)continue;
                Q[rear++] = v;
                dep[v] = dep[u] + 1;
                gap[dep[v]]++;
            }
        }
    }
    int S[MAXN];
    int sap(int start,int end,int N)
    {
        BFS(start,end);
        memcpy(cur,head,sizeof(head));
        int top = 0;
        int u = start;
        int ans = 0;
        while(dep[start] < N)
        {
            if(u == end)
            {
                int Min = INF;
                int inser;
                for(int i = 0;i < top;i++)
                    if(Min > edge[S[i]].cap - edge[S[i]].flow)
                    {
                        Min = edge[S[i]].cap - edge[S[i]].flow;
                        inser = i;
                    }
                for(int i = 0;i < top;i++)
                {
                    edge[S[i]].flow += Min;
                    edge[S[i]^1].flow -= Min;
                }
                ans += Min;
                top = inser;
                u = edge[S[top]^1].to;
                continue;
            }
            bool flag = false;
            int v;
            for(int i = cur[u]; i != -1; i = edge[i].next)
            {
                v = edge[i].to;
                if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u])
                {
                    flag = true;
                    cur[u] = i;
                    break;
                }
            }
            if(flag)
            {
                S[top++] = cur[u];
                u = v;
                continue;
            }
            int Min = N;
            for(int i = head[u]; i != -1; i = edge[i].next)
                if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)
                {
                    Min = dep[edge[i].to];
                    cur[u] = i;
                }
            gap[dep[u]]--;
            if(!gap[dep[u]])return ans;
            dep[u] = Min + 1;
            gap[dep[u]]++;
            if(u != start)u = edge[S[--top]^1].to;
        }
        return ans;
    }
    void init(){ tol = 0; memset(head,-1,sizeof(head)); }
    
    int n, m;
    ll work(){
        init();
        int from = 0, to = n + m +1, A;
        for(int i = 1; i <= n; i++){
            scanf("%d", &A);
            add(i, to, A);
        }
        int u, v; ll d;
        ll all = 0;
        for(int i = 1; i <= m; i++){
            scanf("%d %d %d", &u, &v, &d);
            all += d;
            add(from, n+i, d);
            add(n+i, u, INF);
            add(n+i, v, INF);
        }
        return all - sap(from, to,to+1);
    }
    int main(){
        while(cin>>n>>m)
            cout<<work()<<endl;
        return 0;
    }
    


  • 相关阅读:
    精华网站链接
    面向对象的CSS注意事项
    java 汉字按照指定字符集转换为二进制编码 并把二进制编码转换为对应的汉字 方法
    91环境
    windows下git代码提交情况统计
    git分支管理的使用案例及深入分析
    我在软件园二期的小花园捡起了一片树叶
    sslvpn连接:
    jetbrains register ways
    angular directive实现触底加载效果一则
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5250126.html
Copyright © 2011-2022 走看看