【BZOJ4375】Selling Tickets 随机化

【BZOJ4375】Selling Tickets

Description

厨师在一次晚宴上准备了n道丰盛的菜肴,来自世界各地的m位顾客想要购买宴会的门票。每一位顾客都有两道特别喜爱的菜,而只要吃到了至少一道他喜爱的菜,这位顾客就会感到很高兴。当然,每道菜最多只能供应给一位顾客。厨师想要卖出尽可能多的门票,但同时要能够保证,无论哪些顾客购买门票,所有到来的顾客都能感到高兴。现在,厨师想要问你,他最多能够卖多少门票?

Input

输入的第一行包含一个正整数T,表示数据组数。
对于每组数据,第一行包含一对整数n和m,分别表示菜肴的数量与顾客的数量。接下来m行,第i行的两个正整数Ai, Bi代表第i位顾客喜爱的两道菜的编号。相邻的两组数据之间用一个空行分隔。

Output

输出总共T行,对于每组数据,输出一个整数,表示厨师最多能售出的门票数。

Sample Input

3
6 4
1 2
1 2
3 4
5 6

6 5
1 2
1 2
1 2
3 4
5 6

4 5
1 2
1 3
1 4
2 3
3 4

Sample Output

4
2
4

HINT

对于第二组数据,厨师不能卖3张门票。因为如果顾客1, 2, 3购买门票,厨师是不可能用菜肴1, 2满足三个顾客的要求的。
【数据规模与约定】
1≤T≤15,   2≤n≤200,   0≤m≤500
1≤Ai, Bi≤n且Ai≠Bi

题解:我想不出正解,居然采用随机化;并且随机化写挂了,还针对数据进行随机化,我真是太无耻了~

简单的想法就是每次random_shuffle一个序列,沿着这个序列从左到右一直卖,如果卖到第i+1个卖不出去了,就用i更新答案。如何判定能不能卖出去呢?二分图最大匹配即可。

但是这种随机化策略实在是naive,我们考虑优化,如果卖到i+1个卖不出去了,我们看一下第i+1个人在二分图最大匹配上一共试图匹配了多少个人,即交错环的大小。并用交错环的大小来更新答案,然后就切了~

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int n,m,S,T,ans,cnt,now,sum;
int A[510],B[510],vis[510],head[1010],p[1010],to[10010],next[10010],from[210];
void add(int a,int b)
{
	to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
	return ret*f;
}
int dfs(int x)
{
	sum++;
	for(int i=head[x];i!=-1;i=next[i])
	{
		if(vis[to[i]]!=now)
		{
			vis[to[i]]=now;
			if(!from[to[i]]||dfs(from[to[i]]))
			{
				from[to[i]]=x;
				return 1;
			}
		}
	}
	return 0;
}
void work()
{
	srand(1011);
	n=rd(),m=rd(),ans=m;
	int i,j,a,b;
	memset(head,-1,sizeof(head)),cnt=0,memset(vis,0,sizeof(vis)),now=0;
	for(i=1;i<=m;i++)	a=rd(),b=rd(),add(i,a),add(i,b),p[i]=i;
	for(i=1;i<=2000;i++)
	{
		random_shuffle(p+1,p+m+1);
		memset(from,0,sizeof(from));
		for(j=1;j<=m;j++)
		{
			now++,sum=0;
			if(!dfs(p[j]))
			{
				ans=min(ans,sum-1);
				break;
			}
		}
	}
	printf("%d
",ans);
}
int main()
{
	int T=rd();
	while(T--)	work();
	return 0;
}//3 6 4 1 2 1 2 3 4 5 6 6 5 1 2 1 2 1 2 3 4 5 6 4 5 1 2 1 3 1 4 2 3 3 4
原文地址:https://www.cnblogs.com/CQzhangyu/p/7468908.html