W教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。
现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1,I2,…In}。
实验Ej需要用到的仪器是I的子集RjI。
配置仪器Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。
W教授的任务是找出一个有效算法,
确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。
这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。
对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。
输入包含多组测试数据,每组数据第1行有2个正整数m和n。m是实验数,n是仪器数。
接下来的m行,每行是一个实验的有关数据。
第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。
最后一行的n个数是配置每个仪器的费用。
( 1 <= m,n <= 50 )
每组数据输出一行,为净收益。
2 3
10 1 2
25 2 3
5 6 7
17
经典问题
与上回那个题目相似
LRJ那本书里面有写到
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 2012;
const int MAXM = 1000000;
const int INF = 0x7fffffff;
struct Edge
{
int st, ed;
int next;
int flow;
} edge[MAXM];
int head[MAXN];
int value[MAXN];
int N, M, F, E;
int src, dest;
int seq[MAXM], sl;
int ans = 0;
void add_edge(int u, int v, int w)
{
edge[E].flow = w;
edge[E].st = u;
edge[E].ed = v;
edge[E].next = head[u];
head[u] = E++;
edge[E].flow = 0;
edge[E].st = v;
edge[E].ed = u;
edge[E].next = head[v];
head[v] = E++;
}
int d[MAXN];
bool dinic_bfs(void)
{
int i, j;
memset(d, -1, sizeof(d));
int que[MAXN], rear = 1;
que[0] = src;
d[src] = 0;
for(i = 0; i < rear; i++)
{
for(j = head[que[i]]; j != -1; j = edge[j].next)
{
if(d[edge[j].ed] == -1 && edge[j].flow > 0)
{
d[edge[j].ed] = d[que[i]]+1;
que[rear++] = edge[j].ed;
if(edge[j].ed==dest)
return true;
}
}
}
return false;
}
int dinic_dfs(void)
{
int stk[MAXN], top = 0;
int ret = 0, cur, ptr, pre[MAXN], minf, i;
bool del[MAXN];
memset(del, false, sizeof(del));
stk[top++] = src;
pre[src] = src;
cur = src;
while(top)
{
while(cur != dest && top)
{
for(i = head[cur]; i != -1; i = edge[i].next)
{
if(d[edge[i].ed] == d[cur]+1 && edge[i].flow > 0 && !del[edge[i].ed])
{
stk[top++] = edge[i].ed;
cur = edge[i].ed;
pre[edge[i].ed] = i;
break;
}
}
if(i == -1)
{
del[cur] = 1;
top--;
if(top) cur = stk[top-1];
}
}
if(cur == dest)
{
minf = INF;
while(cur != src)
{
cur = pre[cur];
if(edge[cur].flow < minf) minf = edge[cur].flow;
cur = edge[cur].st;
}
cur = dest;
while(cur != src)
{
cur = pre[cur];
edge[cur].flow -= minf;
edge[cur^1].flow += minf;
if(edge[cur].flow == 0) ptr = edge[cur].st;
cur = edge[cur].st;
}
while(top > 0&& stk[top-1] != ptr) top--;
if(top) cur = stk[top-1];
ret += minf;
}
}
return ret;
}
int Dinic()
{
int ret = 0, t;
while(dinic_bfs())
{
t = dinic_dfs();
if(t) ret += t;
else break;
}
return ret;
}
int main()
{
int n,m;
int i,j,k,x,y;
char c;
while(scanf("%d%d",&m,&n)!=EOF)
{
src=0;
dest=n+m+2;
E=0;
memset(head,-1,sizeof(head));
int sum=0;
for(i=1; i<=m; i++)
{
scanf("%d",&x);
add_edge(i+n,dest,x);
sum+=x;
while(scanf("%d%c",&x,&c))
{
add_edge(x,i+n,INF);
if(c=='/n')
break;
}
}
for(i=1; i<=n; i++)
{
scanf("%d",&x);
add_edge(0,i,x);
}
printf("%d/n",sum-Dinic());
}
return 0;
}