【2010-2011冬令营前的奋斗】【01.14】PKU 1149 (网络流)

 

Pro

         Mirko 在一个由M间上了锁的猪窝组成的农场工作,由于没有钥匙,他打不开任何一个猪窝。客户一个接一个来到农场。他们每一个人都有一些猪窝的钥匙并且希望购买一定数量的猪。

         每天大早 Mirko都能得到关于这一天客户们来到农场的计划的所有信息以便于他能制定一个计划来使卖出的猪的数目最大。

         更详细的流程就是:1。一位顾客到来;2.这位顾客用他所有的钥匙来打开所有对应的猪窝;3. Mirko 在这些猪窝里拿出他想要的数量的猪,并且只要Mirko愿意,他可以重新分配已经打开了的猪窝里的猪;4.这些猪窝重新被锁上。

         假设每个猪窝都可以住无限数目的猪。

         编写程序来找出他当天可以卖出的猪的最大数目。

 

Input

         第一行为两个整数MN1 <= M <= 1000, 表示猪窝的数目  1 <= N <= 100,表示客户的数目)

         第二行为M个数,表示每个猪窝里猪的初始数目,他们都不小于0且不大于1000

         接下来的N行首先有一个数K表示序号为行号的客户的钥匙数,然后K个数分别表示各钥匙所能开的门号(按升序排列) 然后有一个数 表示当前客户想要买的猪的个数

 

Output

         只有一行,为猪的最大出售数量。

Sample Input

3 3

3 1 10

2 1 2 2

2 1 3 3

1 2 6

Sample Output

7


Solution

    这是一道最大流的题,一开始我的做法是

    1:建图,将源点指向各个客户的弧的容量为各客户所开的猪窝的数目总数,如果有某个客户要开的猪窝在之前有其他的顾客开过了,则在这两个顾客之间连一个容量为无限大的弧,各顾客在向汇点连一条容量为其需求量的弧。然后BFS一下求出层次图,然后用Dinic求最大流:

#include<cstring>
#include<stdio.h>
using namespace std;

int m,n,sflow = 0,num[1010],pre[1010],flow[110][110],max = 0,d[110];

int min(int a,int b)
{
    return (a > b ? b : a);
}
int bfs(int s)
{
    int q[1100];
    q[0] = s;
    memset(d,-1,sizeof(d));
    d[s] = 0;
    int fro = 0,rea = 1;
    while (fro < rea)
    {
        int t = q[fro++];
        for (int i = 0;i <= n + 1;++i)
        {
            if ((d[i] == -1) && (flow[t][i] > 0))
            {
                d[i] = d[t] + 1;
                q[rea++] = i;
            }
        }
    }
    if (d[n + 1] >= 0)
        return 1;
    else
        return 0;
}

int dinic(int t,int sum)
{
    if (t == n + 1)
        return sum;
    int s = sum;
    for (int i = 0;(i <= n + 1) && sum;++i)
    {
        if ((d[i] == d[t] + 1) && (flow[t][i] > 0))
        {
            int j = dinic(i,min(sum,flow[t][i]));
            flow[t][i] -= j;
            flow[i][t] += j;
            sum -= j;
        }
    }
    return s - sum;
}

int main()
{
    freopen("pigs.in","r",stdin);
    freopen("pigs.out","w",stdout);
    scanf("%d%d",&m,&n);
    for (int i = 1;i <= m;++i)
    {
        scanf("%d",&num[i]);
        sflow += num[i];
    }
    memset(pre,0,sizeof(pre));
    for (int i = 1;i <= n;++i)
    {
        int a;
        scanf("%d",&a);
        for (int j = 1;j <= a;++j)
        {
            int k;
            scanf("%d",&k);
            if (!pre[k])
                flow[0][i] += num[k];
            else
                flow[pre[k]][i] = sflow;
            pre[k] = i;s
        }
        scanf("%d",&a);
        flow[i][n + 1] = a;
    }
    using::max; 
    while (bfs(0))
        max += dinic(0,20000000);
    printf("%d",max);
    return 0;
}

  这一个程序我觉得没有什么错误,而且谢老师给的数据也全过的,可正当我兴致勃勃地发到POJ上准备AC的时候,却意外的发现竟然WA了!这太奇怪的,我又反复校对了几遍可是实在找不到错误,无奈去问基爷,他的这道题已经AC了,经过他的一番指点,我还是没有找出错误,然后他给了我一个模版,我对着这个模版比照了一遍,发现他的这个做法和我的有一些不同,多了几个操作,但是还是不明白我的错在哪里了,实在奇怪,把他的模版交上去结果就AC掉了,太奇怪了...

 

  这里贴出AC的模版:

dinic
1 const maxn=100+5; maxm=1000+5; oo=maxlongint shr 1;
2  var n,m,s,t,i,j,x,e,ans:longint;
3 d,fir,pre:array[1..maxm]of longint;
4 g:array[1..maxn,1..maxn]of longint;
5 q:array[1..2*(maxn*maxm+maxn)]of longint;
6
7
8  function improve:longint;
9  var i,j,k:longint;
10  begin
11 i:=pre[t];j:=oo;
12 while i>0 do begin
13 if g[i,fir[i]]<=j then begin j:=g[i,fir[i]];k:=i; end;
14 i:=pre[i];
15 end;
16 i:=pre[t];
17 while i>0 do begin
18 dec(g[i,fir[i]],j);inc(g[fir[i],i],j);
19 i:=pre[i];
20 end;
21 improve:=k;inc(ans,j);
22  end;
23
24  procedure dfs;
25  var i,k:longint;
26 ok:boolean;
27  begin
28 for i:=1 to n do fir[i]:=1;
29 pre[s]:=0;i:=s;
30 while i>0 do begin
31 ok:=false;
32 for k:=fir[i] to n do
33 if (d[i]+1=d[k])and(g[i,k]>0) then begin
34 pre[k]:=i;fir[i]:=k;i:=k;ok:=true;
35 if k=t then i:=improve;
36 break;
37 end;
38 if not ok then begin
39 d[i]:=-1;i:=pre[i];
40 end;
41 end;
42  end;
43  function bfs:boolean;
44  var st,ed,i,k:longint;
45  begin
46 st:=0;ed:=1;q[1]:=s;
47 fillchar(d,sizeof(d),$FF);
48 d[s]:=0;
49 while st<ed do begin
50 inc(st);i:=q[st];
51 for k:=1 to n do
52 if (d[k]=-1)and(g[i,k]>0) then begin
53 d[k]:=d[i]+1;inc(ed);q[ed]:=k;
54 if k=t then exit(true);
55 end;
56 end;
57 bfs:=false;
58  end;
59
60  begin
61
62 readln(m,n);s:=n+1;t:=n+2;
63 for i:=1 to m do read(d[i]);
64 for i:=1 to n do begin
65 read(x);
66 for j:=1 to x do begin
67 read(x);
68 if fir[x]=0 then
69 inc(g[s,i],d[x])
70 else g[fir[x],i]:=oo;
71 fir[x]:=i;
72 end;
73 readln(x);g[i,t]:=x;
74 end;
75 n:=n+2;
76 while bfs do
77 dfs;
78 writeln(ans);
79
80  end.
81  

 

 

 

 实在不知道我错在了哪里,求解释啊!!

posted @ 2011-01-16 13:39  Neroysq  阅读(301)  评论(0编辑  收藏  举报