P4174 [NOI2006] 最大获利 最大闭合子图

在这里插入图片描述

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#define INF 0x3f3f3f3f

using namespace std;

const int N = 5e3 + 5e4 + 10,M = (5e3 + 5e4 * 3 + 10) * 2;
typedef long long ll;

int head[N],to[M],last[M],c[M],cnt;
void add(int a,int b,int c1,int c2){
    to[++cnt] = b;
    c[cnt] = c1;
    last[cnt] = head[a];
    head[a] = cnt;
    to[++cnt] = a;
    c[cnt] = c2;
    last[cnt] = head[b];
    head[b] = cnt;
}

int n,m,a[N],S,T,ans;

int d[N],cur[N];
bool bfs(){
    memset(d,0,sizeof d);
    queue<int>q;
    q.push(S);
    d[S] = 1;cur[S] = head[S];
    while(q.size()){
        int p = q.front();
        q.pop();
        for(int i = head[p]; i != -1; i = last[i]){
            int j = to[i];
            if(!d[j] && c[i]){
                cur[j] = head[j];
                d[j] = d[p] + 1;
                q.push(j);
            }
        }
    }
    if(d[T]) return true;
    return false;
}

ll dfs(int x,ll sum){
    if(x == T) return sum;
    ll used = 0;
    for(int i = cur[x]; i != -1; i = last[i]){
        cur[x] = i;
        int j = to[i];
        if(d[j] == d[x] + 1 && c[i]){
            ll dd = dfs(j,min(1ll * c[i],sum - used));
            used += dd;
            c[i] -= dd;
            c[i ^ 1] += dd;
        }
    }
    if(!used) d[x] = -1;
    return used;
}

ll dinic(){
    ll sum = 0;
    while(bfs()){
        sum += dfs(S,INF);
    }
    return sum;
}
int main(){
    memset(head,-1,sizeof head);
    cnt = 1;
    cin >> n >> m;
    S = 0,T = n + m + 1;
    for(int i = 1; i <= n; i++){
        scanf("%d",&a[i]);
        add(i,T,a[i],0);
    }

    ans = n;
    ll sum = 0;
    for(int i = 1; i <= m; i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        sum += z;
        add(S ,++ans,z,0);
        add(ans,x,INF,0);
        add(ans,y,INF,0);
    }

    cout << sum - dinic() <<endl;




    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值