poj 2584 T-Shirt Gumbo(最大流)

Sample Input


START 1
ST
0 0 1 0 0
END
START 2
SS TT
0 0 1 0 0
END
START 4
SM ML LX XT
0 1 1 1 0
END
ENDOFINPUT


Sample Output

T-shirts rock!
I'd rather not wear a shirt anyway...
I'd rather not wear a shirt anyway...
Source


题意:有n个同学要求订购衣服,每个同学可以接收的衣服型号已知(一个人一件衣服),现在每个型号的衣服数量已知,问能不能满足同学的要求?

思路:可行性问题,此题方法很多,多重二分匹配、BFS等。增加源汇点s,t,每个同学与其所接受的型号连一条1的边,s与同学连INF边,型号和t连val (val 是此型号的数量),然后求最大流......



#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<stack>
#include<queue>
#include <iomanip>
#include<iostream>
#include<algorithm>
using namespace std ;
const int N=100 ;
const int M=N*N;
const int inf=1<<30 ;
struct node
{
	int u,v,c,next;
}edge[M];
int head[N],pre[N],dis[N],cur[N],gap[N],need[N];
int top ,s,t,n,nv;

void add(int u ,int v, int c)
{
	   edge[top].u=u;
	   edge[top].v=v;
	   edge[top].c=c;
	   edge[top].next=head[u];
	   head[u]=top++;
	   edge[top].u=v;
	   edge[top].v=u;
	   edge[top].c=0;
	   edge[top].next=head[v];
	   head[v]=top++;	
}

int ISP()
{
	int max_flow=inf ,flow=0,mindis,u,v;
	memset(gap,0,sizeof(gap));
	memset(dis,0,sizeof(dis));
	for(int i = 0 ; i <= nv ; i++)   cur[i]=head[i] ;
	pre[s]=u=s;
	gap[s]=nv;
	while(dis[s] < nv)
	{
		   loop :
		   	  for(int &i=cur[u] ; i!=-1 ;i=edge[i].next)
		   	  {
		   	  	   v=edge[i].v ;
		   	  	   if(edge[i].c > 0 && dis[u] == dis[v]+1 )
		   	  	   {
		   	  	   	      if(max_flow > edge[i].c )
		   	  	   	           max_flow=edge[i].c  ;
		   	  	   	        pre[v]=u;
						    u=v;
							if(v==t)
							{
								  for(u=pre[v] ; v!=s ; v=u,u=pre[u])
								  {
								  	   edge[cur[u]].c -= max_flow ;
								  	   edge[cur[u]^1].c += max_flow ;
								  }
								  flow += max_flow ; 
								  max_flow = inf ;
							}			   
		   	  	   	      goto loop ;
		   	  	   }
		   	  }
		      mindis=nv ;
		      for(int i = head[u] ; i!=-1 ; i=edge[i].next)
		      {
		      	    v=edge[i].v;
		      	    if(edge[i].c >0 && dis[v] < mindis)
		      	    {
		      	    	  mindis=dis[v];
		      	    	  cur[u]=i;
		      	    }
		      }
		   if(--gap[dis[u]]==0)  break ;
		   gap[ dis[u]=mindis+1 ]++;
		  u=pre[u];
	}
	 return flow ;
}

void init()
{
	memset(head,-1,sizeof(head));
	memset(need,0,sizeof(need));
	top=0;
	need['S'] = 1;
    need['M'] = 2;
    need['L'] = 3;
    need['X'] = 4;
    need['T'] = 5;
	
}

int input()
{
	   string op ;
	   int k;
	   cin>>op ;
	   if(op.length()>6)   //结束标志 
	       return 1 ;
	   cin>>n;
	   s=0;t=n+5+1 ; nv=t+1 ;
	   for(int j = 1; j <= n ; j++)
	   {
	      cin>>op ;           //每个同学与对应的型号连边 
	      for(int i = need[op[0]] ; i <= need[op[1]] ; i++	)
	               add(j,n+i,1);
	   	   add(s,j,1);  //源点S与同学连边 
	  }
	  for(int i = 1 ; i <= 5 ; i++)
	  {
	  	    cin>>k ;
	  	    add(n+i,t,k);  //型号和汇点连边 
	  } 
	  cin>>op ;
	  return 0;
}

void work()
{
	int ans=ISP();
	if(ans==n)
	    printf("T-shirts rock!\n");
    else
        printf("I'd rather not wear a shirt anyway...\n");

}

int main()
{
	 while(1)
	 {
	 	    init();    //初始化 
	 	    int res=input();  //建图 
			if(res)      //结束 
			   break;
			work();
	 }
	return 0;	
} 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值