POJ 1149 好题!

网络流好题:

这道题目的大意是这样的:

  • 有 M 个猪圈(M ≤ 1000),每个猪圈里初始时有若干头猪。
  • 一开始所有猪圈都是关闭的。
  • 依次来了 N 个顾客(N ≤ 100),每个顾客分别会打开指定的几个猪圈,从中买若干头猪。
  • 每个顾客分别都有他能够买的数量的上限。
  • 每个顾客走后,他打开的那些猪圈中的猪,都可以被任意地调换到其它开着的猪圈里,然后所有猪圈重新关上。
问总共最多能卖出多少头猪。

由于这题的思路我没有想出来,而是学习了这篇博客,大家可以看一下。网上思路都差不多,这篇写得很好。

这题构图还是弄了我很久... 最终自己还是没能构出来,多学习多想想吧。

#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define MN 1111
#define INF 0x0FFFFFFF
#define CC(a,what) memset( a,what,sizeof(a) )
template<class T> inline void checkmin( T &a,T b ){ if(a>b||a==-1) a=b; } 
using namespace std;

int M,N,s,t;
int maze[MN][MN],cur[MN],pre[MN],dis[MN],gap[MN];

void setG()
{
     int cap[1111],keyn,v;
     int pre[1111];
     CC(pre,0);CC(maze,0);
     s=0;t=N+1; 
     for( int i=1;i<=M;i++ )
          scanf( "%d",&cap[i] );
     for( int i=1;i<=N;i++ )
     {
          scanf( "%d",&keyn );
          for( int j=1;j<=keyn;j++ )
          {
               scanf( "%d",&v );
               if( pre[v]==0 )
                   maze[s][i]+=cap[v];
               else
                   maze[pre[v]][i]=INF;
               pre[v]=i;
          }
          scanf( "%d",&maze[i][t] );
     }
}

int sap()
{
    CC(cur,0),CC(dis,0),CC(gap,0);
    int u=pre[s]=s,maxflow=0,aug=-1;
    gap[0]=t+1;
    while( dis[s]<=t ){
loop:
           for( int v=cur[u];v<=t;v++ )
           if( maze[u][v]&&dis[u]==dis[v]+1 )
           {
               cur[u]=v;
               checkmin( aug,maze[u][v] );
               pre[v]=u;
               u=v;
               if( v==t )
               {
                   maxflow+=aug;
                   for( u=pre[u];v!=s;v=u,u=pre[u] )
                   {
                        maze[u][v]-=aug;
                        maze[v][u]+=aug;
                   }
                   aug=-1;
               }
               goto loop;
           }
           int mind=t;
           for( int v=0;v<=t;v++ )
           if( maze[u][v]&&mind>dis[v] )
           {
               cur[u]=v;
               mind=dis[v];
           }
           if( --gap[dis[u]]==0 )break;
           gap[dis[u]=mind+1]++;
           u=pre[u]; 
    }
    return maxflow;
}

int main()
{
    while( scanf("%d%d",&M,&N)!=EOF )
    {
           setG();
           printf("%d\n",sap());
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值