POJ2584 T-Shirt Gumbo 最大流

算是最大流基础题了吧。

构图:多出一个源点start,一个汇点final

源点到5个衣服的边权值是每个衣服的数量数。

然后每个衣服到匹配的人的边权值都是1,然后每个人到汇点的边权值都是1.

这样最大流一下,其实就是用最大流求最大匹配。

#include<iostream>
#include<queue>
using namespace std;
const int N=200;
const int M=2000;
char range[N][2];
bool visit[N];
int pre[N];
int k=1;
int start;
int final;
int n;
char getcha[6]={'0','S','M','L','X','T'};
int getin(char a)
{
	switch(a)
	{
	case 'S':return 1;
	case 'M':return 2;
	case 'L':return 3;
	case 'X':return 4;
	case 'T':return 5;
	}
}
struct node
{
	int v,w,next,re;
}edge[M];
int edgehead[N];
void addedge(int a ,int b,int w)
{
	edge[k].v=b;
	edge[k].w=w;
	edge[k].next=edgehead[a];
	edge[k].re=k+1;
	edgehead[a]=k++;
	edge[k].v=a;
	edge[k].w=0;
	edge[k].next=edgehead[b];
	edge[k].re=k-1;
	edgehead[b]=k++;
}
bool bfs()
{
	memset(visit,0,sizeof(visit));
	memset(pre,0,sizeof(pre));
	queue<int> que;
	que.push(start);
	visit[start]=true;
	while(!que.empty())
	{
		int now=que.front();
		que.pop();
		for(int i=edgehead[now];i!=0;i=edge[i].next)
		{
			if(edge[i].w>0&&!visit[edge[i].v])
			{
				visit[edge[i].v]=true;
				que.push(edge[i].v);
				pre[edge[i].v]=i;
				if(edge[i].v==final)
					return true;
			}
		}
	}
	return false;
}
void solve()
{
	int ans=0;
	while(bfs())
	{
		int now=final;
		while(now!=start)
		{
			int t=pre[now];
			edge[t].w-=1;
			edge[edge[t].re].w+=1;
			now=edge[edge[t].re].v;
		}
		ans++;
	}
	if(ans<n)
		printf("I'd rather not wear a shirt anyway...\n");
	else
		printf("T-shirts rock!\n");


}
int main()
{
	char str[20];
	while(scanf("%s %d",str,&n),str[0]=='S')
	{
		k=1;
		start=n+6;
		final=n+7;
		memset(edgehead,0,sizeof(edgehead));
		memset(edge,0,sizeof(edge));
		memset(pre,0,sizeof(pre));
		for(int i=1;i<=n;i++)
		{
			scanf("%s",range[i]);
			for(int j=getin(range[i][0]);j<=getin(range[i][1]);j++)
			{
				addedge(j,i+5,1);
			}
		}
		int tmp;
		for(int i=1;i<=5;i++)
		{
			scanf("%d",&tmp);
			addedge(n+5+1,i,tmp);
		}
		for(int i=1;i<=n;i++)
		{
			addedge(5+i,n+5+2,1);
		}
		solve();
		scanf("%s",str);
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值