【網絡流】太空飛行計畫

来源:互联网 发布:园林绿化预算软件 编辑:程序博客网 时间:2024/04/27 13:54
DescriptionW 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1, I2,…In}。实验Ej需要用到的仪器是I的子集Rj ÍI。配置仪器Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。Input文件第1行有2 个正整数m和n。m是实验数,n是仪器数。接下来的m 行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。最后一行的n个数是配置每个仪器的费用。Output 第1行是实验编号;第2行是仪器编号;最后一行是净收益Sample Input2 3                      10 1 2                25 2 3                    5 6 7Sample Output1 21 2 31 7

這道題是最大獲利的翻版……

只需將最後的方案輸出即可。

Accode:

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <bitset>using std::cin;using std::bitset;const char fi[] = "shut.in";const char fo[] = "shut.out";const int maxN = 110;const int MAX = 0x3fffff00;const int MIN = -MAX;int map[maxN][maxN];int f[maxN][maxN];int d[maxN], cnt[maxN];int t[maxN], ele[maxN][maxN];bitset <maxN> expr, instr;int N, M, n, ans, c;  void init_file()  {    freopen(fi, "r", stdin);    freopen(fo, "w", stdout);    std::ios::sync_with_stdio(false);  }  void readdata()  {    cin >> M >> N;    n = M + N + 2;    for (int i = 2; i < M + 2; ++i)    {      cin >> c;      ans += c;      map[1][i] = f[1][i] = c;      while (1)      {        if (cin.peek() == '\n') break;        cin >> c;        ele[i - 1][++t[i - 1]] = c;        map[i][c + M + 1] = f[i][c + M + 1] = MAX;      }    }    for (int i = M + 2; i < n; ++i)    {      cin >> c;      map[i][n] = f[i][n] = c;    }  }  int Sap(int u, int Lim)  {    if (u == n) return Lim;    int tmp = 0;    for (int v = 1; v < n + 1; ++v)     if (f[u][v] > 0 && d[u] == d[v] + 1)      {        int k = Sap(v, std::min(Lim          - tmp, f[u][v]));        if (k <= 0) continue;        f[u][v] -= k;        f[v][u] += k;        if ((tmp += k) == Lim) return tmp;      }    if (d[1] >= n) return tmp;    if ((--cnt[d[u]]) <= 0) d[1] = n;    ++cnt[++d[u]];    return tmp;  }  void work()  {    cnt[0] = n;    while (d[1] < n) ans -= Sap(1, MAX);    if (!ans) {printf("0"); return; }    expr.set();    instr.set();    int k;    for (k = 0; k < n; ++k)      if (!cnt[k]) break;//找到斷點。    for (int i = 2; i < n; ++i)     if (d[i] < k)      {        if (i > M + 1) instr.reset(i - M - 1);        else expr.reset(i - 1);      }//在斷點以下的點不被選中。    for (int i = 1; i < M + 1; ++i)      if (expr.test(i)) printf("%d ", i);    printf("\n");    for (int i = 1; i < N + 1; ++i)      if (instr.test(i)) printf("%d ", i);    printf("\n%d", ans);  }int main(){  init_file();  readdata();  work();  exit(0);}