• poj 1149 PIGS 最大流 建图


    题目链接

    题意

    (n)个顾客要买猪,每个人希望买若干头猪;一共有(m)个猪圈,每个猪圈里有若干头猪。

    (i)个顾客有(k_i)把钥匙,可以打开一些指定的猪圈门,并且买这些猪圈里的猪;在他离开之前,这些猪圈里的猪可以随意交换位置,然后猪圈门被关上。

    问最多可以卖出去多少头猪?

    建图方式

    首先要加的一些边是很显然的:

    1. 源点(slongrightarrow)每个顾客,边权为顾客希望买的猪的个数;

    2. 每个猪圈(longrightarrow)汇点(t),边权为这个猪圈里猪的个数;

    3. 每个顾客到他可以打开的猪圈门连条边,边权为(inf)

    再来考虑题中的特殊条件,每一次打开的所有猪圈的猪可以任意交换位置,这意味着什么呢?

    考虑:

    (i)个顾客打开第(y)扇猪圈门,在他打开第(y)扇门的时候,里面除了会有(y)扇门原来里面的猪,还会有之前经过交换而来的猪,而交换的来源,就是在此之前打开过第(y)扇门的所有顾客,他们打开的其他门。

    这就意味着当前打开第(y)扇门的顾客,他拥有之前所有打开过第(y)扇门的顾客的选择

    于是,可以 在当前打开第(y)扇门的顾客 到 之前所有打开过第(y)扇门的顾客 之间连条边权为(inf)的边。

    进一步的,因为这个关系具有传递性,所有只需在 当前打开第(y)扇门的顾客 和 上一位打开第(y)扇门的顾客 之间连边即可。

    Code

    #include <stdio.h>
    #include <iostream>
    #include <cstring>
    #include <queue>
    #include <vector>
    #define maxm 200010
    #define maxn 1010
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long LL;
    int n, m, x;
    struct Edge { int to, ne, c; }edge[maxm];
    int dep[maxn], ne[maxn], f,d, tot, s,t, vis[maxn];
    void add(int u, int v, int c) {
        edge[tot] = {v, ne[u], c};
        ne[u] = tot++;
        edge[tot] = {u, ne[v], 0};
        ne[v] = tot++;
    }
    int bfs(int src) {
        memset(dep, 0, sizeof dep);
        dep[src] = 1;
        queue<int> q;
        while (!q.empty()) q.pop();
        q.push(src);
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int i = ne[u]; ~i; i = edge[i].ne) {
                int v = edge[i].to;
                if (edge[i].c > 0 && !dep[v]) dep[v] = dep[u] + 1, q.push(v);
            }
        }
        return dep[t];
    }
    int dfs(int u, int flow) {
        if (u == t) return flow;
        int ret = 0;
        for (int i = ne[u]; ~i; i = edge[i].ne) {
            int v = edge[i].to;
            if (edge[i].c > 0 && dep[v] == dep[u] + 1) {
                int c = dfs(v, min(flow-ret, edge[i].c));
                edge[i].c -= c;
                edge[i^1].c += c;
                ret += c;
                if (ret == flow) break;
            }
        }
        if (!flow) dep[u] = 0;
        return ret;
    }
    int main() {
        scanf("%d%d", &m, &n);
        s = 0, t = n+m+1, tot = 0, memset(ne, -1, sizeof(ne));
        memset(vis, -1, sizeof(vis));
        for (int i = 1; i <= m; ++i) {
            scanf("%d", &x);
            add(n+i, t, x);
        }
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &x);
            while (x--) {
                int y;
                scanf("%d", &y);
                if (~vis[y]) add(i, vis[y], inf);
                vis[y] = i;
                add(i, n+y, inf);
            }
            scanf("%d", &x);
            add(s, i, x);
        }
        int ans=0, ret;
        while (bfs(s)) {
            while (ret = dfs(s, inf)) ans += ret;
        }
        printf("%d
    ", ans);
    
        return 0;
    }
    
    
  • 相关阅读:
    [转]C#、VB.NET使用HttpWebRequest访问https地址(SSL)的实现
    C#设置System.Net.ServicePointManager.DefaultConnectionLimit,突破Http协议的并发连接数限制
    [转]WebBrowser控件禁用超链接转向、脚本错误提示、默认右键菜单和快捷键
    [转]C#打印DataGridView的例子源码
    c# TreeView 父节点选中/不选时子节点都同步选中/不选
    C#中PictureBox异步加载图片
    [转]FusionCharts 3.1 破解版 – 非常好用的Flash图表控件
    配合JavaScript拖动页面中控件
    在ThinkPad T400上安装win2003 所遇问题
    C# 抛弃MoveTo来实现文件重命名
  • 原文地址:https://www.cnblogs.com/kkkkahlua/p/7770801.html
Copyright © 2020-2023  润新知