Codeforces contest 311 problem E. Biologist(最大权闭合子图)

传送门


题目大意

这里写图片描述


题解

GDKOI考成了垃圾,博客都不想写了,键盘都不想碰了,人生都觉得无意义了。

一个简单的最大权闭合子图的模型。按照套路,将条件和变量都建点。S代表0的选择集合,T是1的集合。对于每个变量,是0与S连,否则与T连,如果割掉代表要花费V[i]的代价;对于每个条件,先收集其价值,再在连边上放上其价值(+代价),如果割掉就代表不要这部分的价值(+付出代价)。

同样向S或T连边,再向要求的变量连边(或者变量连向条件),容量为INF,代表如果构成S-T路径就要舍弃条件或者修改所连变量的所有值。然后跑一遍最小割。

时间复杂度玄学。


代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define maxn 100010
#define maxm 1000100
#define INF 0x7FFFFFFF

using namespace std;

int s, t, cur = -1;
struct List{
    int obj, cap;
    List *next, *rev;
}*head[maxn], *iter[maxn], Edg[maxm];

void Addedge(int a, int b, int c){
    Edg[++cur].next = head[a];
    Edg[cur].obj = b;
    Edg[cur].cap = c;
    Edg[cur].rev = Edg+(cur^1);
    head[a] = Edg+cur;
}

int q[maxn], level[maxn];

bool bfs(){
    int hh = 0, tt = 0;
    for(int i = s; i <= t; i++)  level[i] = -1;
    level[s] = 0;
    q[0] = s;

    while(hh <= tt){
        int now = q[hh++];
        for(List *p = head[now]; p; p = p->next){
            int v = p->obj, c = p->cap;
            if(c && level[v] == -1){
                level[v] = level[now] + 1;
                q[++tt] = v;
            }
        }
    }
    return ~ level[t];
}

int Dinic(int now, int f){
    if(now == t || !f)  return f;
    int ret = 0;
    for(List *&p = iter[now]; p; p = p->next){
        int v = p->obj, c = p->cap;
        if(c && level[now] + 1 == level[v]){
            int d = Dinic(v, min(f, c));
            f -= d;
            p->cap -=d;
            ret += d;
            p->rev->cap += d;
            if(!f)  break;
        }
    }
    return ret;
}

int MinCut(){
    int flow = 0;
    while(bfs()){
        for(int i = s; i <= t; i++)  iter[i] = head[i];
        flow += Dinic(s, INF);
    }
    return flow;
}

int sum;

int n, m, g;

int V[maxn], F[maxn];

int main(){

    scanf("%d%d%d", &n, &m, &g);

    for(int i = 1; i <= n; i++)  scanf("%d", &F[i]);

    for(int i = 1; i <= n; i++)  scanf("%d", &V[i]);

    s = 1;  t = s + n + m + 1;

    for(int i = s; i <= t; i++)  head[i] = NULL;

    for(int i = 1; i <= n; i++){
        if(!F[i]){
            Addedge(s, s+i, V[i]);
            Addedge(s+i, s, 0);
        }
        else{
            Addedge(s+i, t, V[i]);
            Addedge(t, s+i, 0); 
        }
    }

    int f, w, k, x;
    for(int i = 1; i <= m; i++){
        scanf("%d%d%d", &f, &w, &k);
        sum += w;
        for(int j = 1; j <= k; j++){
            scanf("%d", &x);
            if(!f){
                Addedge(s+n+i, s+x, INF);
                Addedge(s+x, s+n+i, 0);
            }
            else{
                Addedge(s+x, s+n+i, INF);
                Addedge(s+n+i, s+x, 0);
            }
        }
        scanf("%d", &x);
        if(!f){
            Addedge(s, s+n+i, w+g*x);
            Addedge(s+n+i, s, 0);
        }
        else{
            Addedge(s+n+i, t, w+g*x);
            Addedge(t, s+n+i, 0); 
        }
    }

    printf("%d\n", sum - MinCut());

    return 0;
} 

人生又是什麼呢 只是不明不白地活著

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,Codeforces Round 511 (Div. 1)是一个比赛的名称。然而,引用内容中没有提供与这个比赛相关的具体信息或问题。因此,我无法回答关于Codeforces Round 511 (Div. 1)的问题。如果您有关于这个比赛的具体问题,请提供更多的信息,我将尽力回答。 #### 引用[.reference_title] - *1* [Codeforces Round 860 (Div. 2)题解](https://blog.csdn.net/qq_60653991/article/details/129802687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces Round 867 (Div. 3)(A题到E题)](https://blog.csdn.net/wdgkd/article/details/130370975)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Codeforces Round 872 (Div. 2)(前三道](https://blog.csdn.net/qq_68286180/article/details/130570952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值