CodeForces 311E Biologist

原创 2015年11月17日 20:52:23

题目大意

给定n只狗,和m个人,每只狗变性需要花费vi的代价,每个人会对一部分狗有一个期望性别(都为雄性或都为雌性),如果性别能够一一对上,就会获得wi的利润,如果不能对上并且这个人比较重要,会减少g的获利。求能获得的最大利润。

解答

很容易能看出这是一个最小割模型,我们先把所有的获利相加得到sum,之后求最小消耗即可。
我们把每只狗变为雌性的代价做为边权连一条从s出来的边,同样把每只狗变为雄性的代价做为边权连一条到t的边。然后把每个希望狗是雄性的人连边到每个他需要的狗,边权为,同样把每个希望狗是雌性的人从每个他需要的狗连一条边到他自己,边权也是
我们定义P={},同样定义Q={}
所以

C(P,Q)=e=tlen(e)+e=slen(e)+e=len(e)

C(P,Q)=

所以求上述图的最小割即可。
附上一张图做参考
其实有图也比较难理解,大家可以自己那组样例算一算
总结起来是一句话:割的时候,雄性的在一起,雌性的在一起,求两个集合之间的割

参考代码

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>

using namespace std;

const int oo = 2147483600;

class Edge
{
    public:
        int to;
        int next;
        int len;
};

Edge es[13107200];
int et = -1;
int head[20000];
int h[20000];
int fl[20000];
int st, th;
int n, m, g;
int sum = 0;
bool dog[20000];
int w[20000];

void addEdge(int u, int v, int l)
{
    et++;
    es[et].to = v;
    es[et].len = l;
    es[et].next = head[u];
    head[u] = et;
    et++;
    es[et].to = u;
    es[et].len = 0;
    es[et].next = head[v];
    head[v] = et;
}

bool bfs()
{
    memset(fl, -1, sizeof(fl));
    queue<int> ser;
    ser.push(st);
    fl[st] = 1;
    int x;
    bool flag = false;
    while (!ser.empty()) {
        x = ser.front();
        ser.pop();
        for (int i = head[x]; i != -1; i = es[i].next) {
            if (es[i].len && fl[es[i].to] == -1) {
                fl[es[i].to] = fl[x] + 1;
                if (es[i].to == th)
                    flag = true;
                ser.push(es[i].to);
            }
        }
    }
    return flag;
}

int dfs(int x, int flow)
{
    if (x == th)
        return flow;
    int cflow = flow;
    int ret;
    for (int &i = h[x]; i != -1; i = es[i].next)
        if (es[i].len && fl[es[i].to] == fl[x] + 1) {
            ret = dfs(es[i].to, min(es[i].len, flow));
            es[i].len -= ret;
            es[i^1].len += ret;
            flow -= ret;
            if (!flow)
                return cflow;
        }
    return cflow - flow;
}

int dinic()
{
    int ans = 0;
    while (bfs()) {
        for (int i = 0; i <= th; i++)
            h[i] = head[i];
        ans += dfs(st, oo);
    }
    return ans;
}

void readin()
{
    memset(head, -1, sizeof(head));
    cin >> n >> m >> g;
    st = 0;
    th = n+m+1;
    int w, k, v;
    bool se;
    for (int i = 1; i <= n; i++)
        cin >> dog[i];
    for (int i = 1; i <= n; i++) {
        cin >> w;
        if (dog[i])
            addEdge(st, i, w);
        else
            addEdge(i, th, w);
    }
    for (int i = 1; i <= m; i++) {
        cin >> se;
        cin >> w >> k;
        sum += w;
        for (int j = 0; j < k; j++) {
            cin >> v;
            if (se)
                addEdge(i+n, v, oo);
            else
                addEdge(v, i+n, oo);
        }
        cin >> v;
        if (v)
            w += g;
        if (se)
            addEdge(st, i+n, w);
        else
            addEdge(i+n, th, w);
    }
}

int main()
{
    ios::sync_with_stdio(false);
    readin();
    sum -= dinic();
    cout << sum;
    return 0;
}

关于codeforces比赛规则介绍(转载)

Codeforces 简称: cf(所以谈论cf的时候经常被误会成TX的那款游戏). 网址: codeforces.com   这是一个俄国的算法竞赛网站,由来自萨拉托夫州立大学、由Mike Mirz...
  • y990041769
  • y990041769
  • 2014年02月19日 08:41
  • 15434

Codeforces 11D A Simple Task 统计简单无向图中环的个数

状态压缩动态规划计算简单无向图中简单环的个数。
  • fangzhenpeng
  • fangzhenpeng
  • 2015年10月12日 19:01
  • 1211

Codeforces 375D 数据结构(好题中的好题, 4解)

题目链接:http://codeforces.com/problemset/problem/375/D 全部代码: 题意:给你一棵树n个点,m次询问(n=100000,m=100000),每个节点有一...
  • c3568
  • c3568
  • 2014年03月25日 19:38
  • 1409

Codeforces 311E. Biologist (最小割)

题目描述传送门题目大意:有n个已经有初值的0/1变量,改变一个变量需要vi的花 费。有m个需求,要求某个集合的变量均为0/1,满足需 求得到wi的收益,对于某些集合不满足时需要付出额外的代价g。求...
  • clover_hxy
  • clover_hxy
  • 2017年07月06日 20:03
  • 163

【Codeforces Round #185】Codeforces 311E Biologist

最小割
  • sdfzyhx
  • sdfzyhx
  • 2017年02月21日 07:50
  • 106

Codeforces 311(div 2):E. Ann and Half-Palindrome

题目描述:           给定半回文子串的定义,现给你一个串S和一个整数K,输出S所有子串中且是半回文排名第K的子串,半回文子串按照字典序升序顺序。(len(S) 分析:    ...
  • Dream_you_to_life
  • Dream_you_to_life
  • 2015年07月08日 13:12
  • 717

Codeforces Round #311 (Div. 2) A~E && DE题解

A Ilya and Diplomas Problem Description:Soon a school Olympiad in Informatics will be held in Ber...
  • qq_27925701
  • qq_27925701
  • 2016年06月12日 21:58
  • 350

【Codeforces#311】 div.2 C--E

C: 题意:一张桌子有n条腿,每条腿都有锯掉所要消耗的能量。一张桌子如果最长的腿超过一半,则称稳定的。问使桌子稳定的最小需要能量。 枚举最长的腿的长度,然后用set维护一下就好了。 #include ...
  • u011332631
  • u011332631
  • 2015年07月06日 20:13
  • 273

codeforces #311 557E E. Ann and Half-Palindrome(trie+dp+dfs)

题目链接: 点击打开链接 题目大意: 给出一个字符串,问这个字符串的是半回文的子串的第k个是什么,半回文就是前一半的奇数位满足回文串的条件 题目分析: 这道题要求输出字典序第k大,那么自然而...
  • qq_24451605
  • qq_24451605
  • 2015年07月02日 22:53
  • 562

Codefores #185E (div1) Biologist

Codefores #185E (div1) Biologist ACM 图论 网络流 最小割
  • dnvtmf
  • dnvtmf
  • 2016年03月11日 10:46
  • 247
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:CodeForces 311E Biologist
举报原因:
原因补充:

(最多只允许输入30个字)