zoukankan      html  css  js  c++  java
  • 【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
  • 相关阅读:
    获取键盘代码
    从一道js笔试题到==运算符的简析
    【物联网智能网关01】通过AD采集获取温湿度
    【物联网智能网关04】WinForm for .NET MF 功能一览
    .NET Micro Framework V4.2 RTM正式发布
    【物联网智能网关02】获取摄像头数据+显示
    .NET Micro Framework开发板用户简明手册(v3.0)
    2011 ARM技术研讨会杂记
    再谈.NET Micro Framework移植
    【.Net MF网络开发板研究06】以太网转串口
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7468908.html
Copyright © 2011-2022 走看看