/**
建图:
<1>: 将顾客看作是除源点和汇点的结点,并且另设两个结点,源点和汇点
<2>:源点和每个猪圈的第一位顾客连边,边的权值是开始时猪圈中猪的数量
<3>:若源点和某个结点有重边,则将权值合并(因此,从原点流出的流量就是所有猪圈所能提供猪的数量)
<4>:顾客j紧跟顾客i打开某个猪圈,则置<i, j>的权值为无穷大,因为顾客j紧跟顾客i之后,迈克可以根据顾客j的需求,调来足够多的猪。
<5>:每个顾客都和汇点连接,边的权值即是每个顾客所希望买的猪的数目(最后流入汇点的流量即是迈克所能卖出猪的数量)
*/
#include <iostream>
#include <cstring>
using namespace std;
const int MAXN = 110;
const int MAXM = 1010;
const int INF = 100000000;
struct ArcType
{
int c, f;
};
ArcType Edge[MAXN][MAXN];
int n;
int MIN(int a, int b)
{
return a < b ? a : b;
}
int fabs(int a)
{
return a < 0 ? (-a) : a;
}
void Ford()
{
int pre[MAXN];
int alpha[MAXN];
int flag[MAXN];
int que[MAXN];
int qs, qe;
while(1)
{
memset(pre, 0xff, sizeof(pre));
memset(flag, 0xff, sizeof(flag));
memset(que, 0, sizeof(que));
memset(alpha, 0, sizeof(alpha));
qs = qe = 0;
que[qe++] = 0;
flag[0] = 0, alpha[0] = INF, pre[0] = 0;
while(qs < qe && (flag[n+1] == -1))
{
int u = que[qs++];
for(int v = 1; v < n+2; ++v)
{
if(flag[v] == -1)
{
if(Edge[u][v].c < INF && Edge[u][v].f < Edge[u][v].c)
{
flag[v] = 0;
pre[v] = u;
alpha[v] = MIN(alpha[u], Edge[u][v].c - Edge[u][v].f);
que[qe++] = v;
}
else if(Edge[v][u].c < INF && Edge[v][u].f > 0)
{
flag[v] = 0;
pre[v] = -u;
alpha[v] = MIN(alpha[u], Edge[v][u].f);
que[qe++] = v;
}
}
}
flag[u] = 1;
}
if(flag[n+1] == -1 || alpha[n+1] == 0)
break;
int k1 = n+1;
int k2 = fabs( pre[k1] );
int a = alpha[n+1];
while(1)
{
if(Edge[k2][k1].c < INF)
Edge[k2][k1].f += a;
else if(Edge[k1][k2].f > 0 && Edge[k1][k2].f < INF)
Edge[k1][k2].f -= a;
if(k2 == 0)
break;
k1 = k2;
k2 = fabs( pre[k1] );
}
}
int Maxflow = 0;
for(int i = 1; i < n+1; ++i)
if(Edge[0][i].c < INF)
Maxflow += Edge[0][i].f;
cout<<Maxflow<<endl;
}
void Inite()
{
int m, k;
cin>>m>>n;
for(int i = 0; i < MAXN; ++i)
for(int j = 0; j < MAXN; ++j)
Edge[i][j].c = Edge[i][j].f = INF;
int house[MAXM];
int last[MAXM];
memset(house, 0, sizeof(house));
memset(last, 0, sizeof(last));
for(int i = 1; i <= m; ++i)
cin>>house[i];
for(int i = 1; i <= n; ++i)
{
int num;
cin>>num;
for(int j = 0; j < num; ++j)
{
cin>>k;
if(last[k] == 0)
{
if(Edge[0][i].c == INF)
Edge[0][i].c = house[k];
else
Edge[0][i].c += house[k];
Edge[0][i].f = 0;//初始时该边的实际流量定义为零流
}
else
{
Edge[ last[k] ][i].c = INF - 1;//保证last[k]买过之后,可以调来足够多的猪供顾客i购买,这个值虽定义的是无穷但是要比无穷小
Edge[ last[k] ][i].f = 0;//因为该边存在,不存在定义的是两点之间是无穷
}
last[k] = i;
}
cin>>Edge[i][n+1].c;
Edge[i][n+1].f = 0;
}
/**
for(int i = 0; i <= n+1; ++i)
{
for(int j = 0; j <= n+1; ++j)
{
if(Edge[i][j].c < INF)
cout<<i<<" -> "<<j<<" : "<<Edge[i][j].c<<endl;
}
}
*/
}
int main()
{
Inite();
Ford();
return 0;
}
poj1149迈克卖猪问题(PIGS)
最新推荐文章于 2022-05-14 17:18:32 发布