zoukankan      html  css  js  c++  java
  • P2762 太空飞行计划问题 (最小割)

    题意:n个实验 每个实验可获利ai元 做每个实验需要几个仪器

       购买每个仪器有不同的花费 不同实验可能会用到同一个仪器 只用购买一次 求最大收益

    题解:............................................

       先讲玄学建图吧

       从s向每个实验连权值为仪器收益的边

       从每个仪器向t连权值仪器花费的边

       实验与仪器之间连INF的边

       答案等于所有实验的收益 减去 (最大流=最小割)

       感性的理解一下.. 你已经获得了实验的收益了 如果当前存在一条s->t的路径 那么就表示你这个实验 还欠缺着某个仪器没买

       因为把仪器割掉的含义是买这个仪器 所以才会减去花费

       如果把实验割掉了 那么显然就是不做这个实验

       然后输出方案也学到一个trick 就是在最后一次bfs的时候 如果当前点跑不到 dis = INF 那么意味着到这个点的边权被减为0了 流满了 就是这个点被割掉了

       在这个题里被割掉了就意味着 选择做实验 买仪器

    #include <bits/stdc++.h>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    
    int n, m, s, t, maxflow, cnt;
    struct node {
        int to, nex, val;
    }E[100005];
    int head[105];
    int cur[105];
    
    void addedge(int x, int y, int va) {
        E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt; E[cnt].val = va;
        E[++cnt].to = x; E[cnt].nex = head[y]; head[y] = cnt; E[cnt].val = 0;
    }
    
    int dep[105];
    int inque[105];
    bool bfs() {
        for(int i = 1; i <= t; i++) dep[i] = INF, inque[i] = 0, cur[i] = head[i];
        queue<int> que;
        que.push(s);
        dep[s] = 0, inque[s] = 1;
    
        while(!que.empty()) {
            int u = que.front();
            que.pop();
            inque[u] = 0;
    
            for(int i = head[u]; i; i = E[i].nex) {
                int v = E[i].to;
                if(E[i].val && dep[v] > dep[u] + 1) {
                    dep[v] = dep[u] + 1;
                    if(!inque[v]) {
                        que.push(v);
                        inque[v] = 1;
                    }
                }
            }
        }
        return dep[t] != INF;
    }
    
    int vis;
    int dfs(int x, int flow) {
        if(x == t) {
            maxflow += flow;
            vis = 1;
            return flow;
        }
    
        int rflow = 0;
        int used = 0;
        for(int i = cur[x]; i; i = E[i].nex) {
            cur[x] = i;
            int v = E[i].to;
            if(E[i].val && dep[v] == dep[x] + 1) {
                if(rflow = dfs(v, min(flow - used, E[i].val))) {
                    used += rflow;
                    E[i].val -= rflow;
                    E[i ^ 1].val += rflow;
                    if(used == flow) break;
                }
            }
        }
        return used;
    }
    
    void dinic() {
        maxflow = 0;
        while(bfs()) {
            vis = 1;
            while(vis) {
                vis = 0;
                dfs(s, INF);
            }
        }
    }
    
    int p[55];
    int c[55];
    int ans[55];
    int viss[55];
    int ned[55][55];
    char tools[10000];
    
    int main() {
        int sum = 0;
        scanf("%d%d", &n, &m);
        s = n + m + 1;
        t = s + 1;
        cnt = 1;
        int ulen;
    
        for(int i = 1; i <= n; i++) {
            scanf("%d", &p[i]);
            sum += p[i];
            addedge(s, i, p[i]);
    
            memset(tools, 0, sizeof(tools));
            cin.getline(tools, 10000);
            ulen = 0;
            int num;
            while(sscanf(tools + ulen, "%d", &num) == 1) {
                ned[i][num] = 1;
                addedge(i, n + num, INF);
    
                if(num == 0) ulen++;
                else {
                    while(num) {
                        num /= 10;
                        ulen++;
                    }
                }
                ulen++;
            }
    
        }
        for(int i = 1; i <= m; i++) scanf("%d", &c[i]);
        for(int i = 1; i <= m; i++) addedge(n + i, t, c[i]);
        dinic();
    
        for(int i = 1; i <= m; i++) {
            for(int j = head[i + n]; j; j = E[j].nex) {
                int v = E[j].to;
                if(v == t) {
                    if(E[j].val == 0) viss[i] = 1;
                    break;
                }
            }
        }
    
        for(int i = 1; i <= n; i++) {
            if(dep[i] != INF) printf("%d ", i);
        }
        puts("");
    
        for(int i = 1; i <= m; i++) {
            if(dep[i + n] != INF) printf("%d ", i);
        }
        puts("");
        printf("%d
    ", sum - maxflow);
        return 0;
    }
    View Code

       

  • 相关阅读:
    CentOS7中Tomcat的安装和配置
    CentOS7中JDK的安装和配置
    Linux基本指令
    MySQL数据库索引:索引介绍和使用原则
    MongoDB基础篇2:数据库/用户/数据集合的增删改
    MongoDB基础篇1:安装和服务配置
    JSTL fn:replace()函数替换 换行符
    LeetCode440. 字典序的第K小数字
    kubeadm搭建kubernetes-1.13.2集群
    kubernetes(k8s)kubectl使用详解
  • 原文地址:https://www.cnblogs.com/lwqq3/p/11198522.html
Copyright © 2011-2022 走看看