POJ 1149 PIGS

Description

Mirko works on apig farm that consists of M locked pig-houses and Mirko can't unlock anypighouse because he doesn't have the keys. Customers come to the farm one afteranother. Each of them has keys to some pig-houses and wants to buy a certainnumber of pigs. 
All data concerning customers planning to visit the farm on that particular dayare available to Mirko early in the morning so that he can make a sales-plan inorder to maximize the number of pigs sold.
 
More precisely, the procedure is as following: the customer arrives, opens allpig-houses to which he has the key, Mirko sells a certain number of pigs fromall the unlocked pig-houses to him, and, if Mirko wants, he can redistributethe remaining pigs across the unlocked pig-houses.
 
An unlimited number of pigs can be placed in every pig-house.
 
Write a program that will find the maximum number of pigs that he can sell onthat day.

Input

The first line ofinput contains two integers M and N, 1 <= M <= 1000, 1 <= N <= 100,number of pighouses and number of customers. Pig houses are numbered from 1 toM and customers are numbered from 1 to N. 
The next line contains M integeres, for each pig-house initial number of pigs.The number of pigs in each pig-house is greater or equal to 0 and less or equalto 1000.
 
The next N lines contains records about the customers in the following form (record about the i-th customer is written in the (i+2)-th line):
 
A K1 K2 ... KA B It means that this customer has key to the pig-houses markedwith the numbers K1, K2, ..., KA (sorted nondecreasingly ) and that he wants tobuy B pigs. Numbers A and B can be equal to 0.

Output

The first and onlyline of the output should contain the number of sold pigs.

Sample Input

3 3

3 1 10

2 1 2 2

2 1 3 3

1 2 6

Sample Output

7

 集训期间,实在太累,不写了。。。。。。待到开学再来慢慢写吧

#include <iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define INF 9999999
using namespace std;

struct Edge
{
	int st, ed;
	int next;
	int flow;
} edge[10010];
int head[10010], out[10010];
int stack[10010], p[10010];
int leve[1010];
int  Count, s, t;

int dist[1010] ,num[110] ,pig[1010];
int n ,m;

void build_edge ( int u, int v, long long flw )
{
	edge[Count].st = u;
	edge[Count].ed = v;
	edge[Count].flow = flw;
	edge[Count].next = head[u];
	head[u] = Count++;

	edge[Count].st = v;
	edge[Count].ed = u;
	edge[Count].flow = 0;
	edge[Count].next = head[v];
	head[v] = Count++;
};

bool BFS()
{
	memset(leve,-1,sizeof(leve));
	int front, rear, u, v, i;
	front = rear = 0;
	p[rear++] = s;
	leve[s] = 0;
	while(front!=rear)
	{
		u = p[front++];
		for (i = head[u];i!=-1;i = edge[i].next )
		{
			v = edge[i].ed;
			if(edge[i].flow > 0&&leve[v]==-1)
			{
				leve[v] = leve[u] + 1;
				p[rear++] = v;
			}
		}
	}
	return leve[t]!=-1;
};

int Dinic ()
{
	int maxFlow = 0 ,re ,er;
	while (BFS())
	{
		int top = 0, u = s, i;
		for(i = s;i <= t;i++)
		{
			out[i] = head[i];
		}

		while(out[s]!=-1)
		{
			er = out[u];
			if(u==t)
			{
				int dd = INF;
				for (i = top - 1;i >=0;i--)
				{
					dd = min (edge[stack[i]].flow,dd);
				}
				for (i = top - 1;i >= 0;i--)
				{
					re = stack[i];
					edge[re].flow -= dd;
					edge[re^1].flow += dd;
					if (edge[re].flow==0)
					{
						top = i;
					}
				}
				maxFlow += dd;
				u = edge[stack[top]].st;
			}
			else if (er!=-1&&edge[er].flow > 0&&leve[u] + 1==leve[edge[er].ed])
			{
				stack[top++] = er;
				u = edge[er].ed;
			}
			else
			{
				while (top > 0&&u!=s&&out[u]==-1)
				{
					u = edge[stack[--top]].st;
				}
				out[u] = edge[out[u]].next;
			}
		}
	}
	return maxFlow;
};

int main()
{
    int x ,len ,ans;
    while(~scanf("%d%d",&m,&n))
    {
        memset(dist,0,sizeof(dist));
        memset(head,-1,sizeof(head));
		Count = 0;
        s = 0;
        t = n + 1;
        for(int i = 1;i<=m;i++)
        {
            scanf("%d",&pig[i]);
        }
        for(int i = 1;i <= n;i++)
        {
            scanf("%d",&len);
            while(len--)
            {
                scanf("%d",&x);
                if(dist[x]==0)
                {
                    num[0] += pig[x];
                }
                else
                {
                    num[dist[x]]++;
                }
                dist[x] = i;
            }
            if(num[0])
            {
                build_edge(0,i,num[0]);
				num[0] = 0;
            }
            for(int j = 1;j<=n;j++)
            {
                if(num[j])
                {
                    build_edge(j,i,INF);
                    num[j] = 0;
                }
            }
            scanf("%d",&x);
            build_edge(i,n + 1,x);
        }
        ans = Dinic();
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值