ACM: 图论题 poj 1149 网络流问题

来源:互联网 发布:java酒店管理系统程序 编辑:程序博客网 时间:2024/05/17 19:14
PIGS

 

Description

Mirko works on a pig farm thatconsists of M locked pig-houses and Mirko can't unlock any pighousebecause he doesn't have the keys. Customers come to the farm oneafter another. Each of them has keys to some pig-houses and wantsto buy a certain number of pigs.
All data concerning customers planning to visit the farm on thatparticular day are available to Mirko early in the morning so thathe can make a sales-plan in order to maximize the number of pigssold.
More precisely, the procedure is as following: the customerarrives, opens all pig-houses to which he has the key, Mirko sellsa certain number of pigs from all the unlocked pig-houses to him,and, if Mirko wants, he can redistribute the remaining pigs acrossthe 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 hecan sell on that day.

Input

The first line of input containstwo integers M and N, 1 <= M <= 1000,1 <= N <= 100, number of pighousesand number of customers. Pig houses are numbered from 1 to M andcustomers are numbered from 1 to N.
The next line contains M integeres, for each pig-house initialnumber of pigs. The number of pigs in each pig-house is greater orequal to 0 and less or equal to 1000.
The next N lines contains records about the customers in thefollowing 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 thepig-houses marked with the numbers K1, K2, ..., KA (sortednondecreasingly ) and that he wants to buy B pigs. Numbers A and Bcan be equal to 0.

Output

The first and only line of theoutput 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

 

题意: Mirko有m个猪屋, 有n个客人要想他买猪, 每位客人会要其中A个猪屋内的共B只猪, Mirko

      可以在客人买了之后将剩下的猪屋内的猪重新安排放置.问Mirko最大可以卖多少只猪.

 

解题思路:

    1. 一开始在纸上画了画, 每间猪屋到每位客人连线, 每间猪屋内的猪的数量已知, 突然发现

       是网络流的问题.(问题的敏感很重要)

     2.设超级源点start = 0, 汇点end = n+1 (n是顾客数), 因为可以调整猪的放置, 并且有2

       个和2个以上选择的顾客需要合并; 因此图需要改一改, start到每位顾客的边的权值是

       全部猪屋的数量总和, 并且当有2个和2个以上的选择的顾客, 这些猪屋之间因为可以重新

       调整, 所以它们之间也要连边权值为无限大(任意调整), 最后就是顾客们到汇点的连边,

       权值当然是每位顾客的需求.

    3. 图建好了, 最大流KM算法即可.

 

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
#define MAX 1105
#define MAXSIZE 115
const int INF = (1<<29);

int n, m;
int cap[MAXSIZE][MAXSIZE], num[MAX], flow[MAXSIZE][MAXSIZE];
int a[MAXSIZE], p[MAXSIZE];
int start, end;
int first[MAX];

inline int min(int a, int b)
{
 return a < b ? a : b;
}

void readGraph()
{
 int i, j, count, temp;
 for(i = 1; i <= m; ++i)
  scanf("%d",&num[i]);
 memset(first, 0, sizeof(first));
 memset(cap, 0, sizeof(cap));
 start = 0, end = n+1;
 for(i = 1; i <= n; ++i)
 {
  scanf("%d",&count);
  for(j = 1; j <=count; ++j)
  {
   scanf("%d",&temp);
   if(first[temp] == 0 ) cap[start][i] += num[temp];
   else cap[first[temp] ][i] = INF;
   first[temp] =i;
  }
  scanf("%d",&temp);
  cap[i][end] = temp;
 }
}

int KM()
{
 int result = 0;
 memset(flow, 0, sizeof(flow));
 queue qu;
 while( true )
 {
  memset(p, -1, sizeof(p));
  memset(a, 0, sizeof(a));
  qu.push(start);
  a[start] = INF;
  while( !qu.empty() )
  {
   int u =qu.front();
   qu.pop();
   for(int v =1; v <= end; ++v)
   {
    if(!a[v] && cap[u][v] >flow[u][v] )
    {
     p[v]= u;
     qu.push(v);
     a[v]= min(a[u], cap[u][v]-flow[u][v]);
    }
   }
  }
  if(a[end] == 0) break;
  for(int u = end; u != start; u= p[u])
  {
   flow[ p[u]][u] += a[end];
   flow[u][ p[u]] -= a[end];
  }
  result += a[end];
 }
 return result;
}

int main()
{
// freopen("input.txt", "r", stdin);
 while( scanf("%d %d", &m,&n) != EOF )
 {
  readGraph();
  printf("%d\n", KM());
 }
 return 0;
}

0 0
原创粉丝点击