• [BZOJ1305][CQOI2009]dance跳舞


    BZOJ
    Luogu
    Description
    一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“单向喜欢”)。每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞。给出每对男孩女孩是否相互喜欢的信息,舞会最多能有几首舞曲?
    Input
    第一行包含两个整数n和k。以下n行每行包含n个字符,其中第i行第j个字符为'Y'当且仅当男孩i和女孩j相互喜欢。
    Output
    仅一个数,即舞曲数目的最大值。
    Sample Input

    3 0
    YYY
    YYY
    YYY
    

    Sample Output

    3
    

    HINT
    N<=50 K<=30

    sol

    首先比较容易想到的应该是二分数目转换成最大流判定的模型。
    那么我们就需要在给每个人的容量限为(mid)的同时,把和不喜欢的人跳舞的容量限为(k)
    所以我们把每个人拆两个点,一个点表示总量,令一个点表示不喜欢的,从总量点向另一个点连容量为(k)的边,表示最多可以往“不喜欢的”那边分(k)的流量。
    具体建图:(假设(i)是男生总量点,(i')是男生不喜欢点,(i'')是女生不喜欢点,(i''')是女生总量点)
    1、(S)(i)(i''')(T)连容量为(mid)的边。
    2、(i)(i')(i'')(i''')连容量为(k)的边。
    3、对于一对男女生(i)(j),若相互喜欢,就从(i)(j''')连边,否则从(i')(j'')连边。
    所以说二分+最大流即可。

    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int inf = 1e9;
    const int N = 250;
    struct edge{int to,next,w;}a[N*N];
    int n,k,s,t,head[N],cnt=1,dep[N],cur[N];
    char g[N][N];
    queue<int>Q;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    void link(int u,int v,int w)
    {
    	a[++cnt]=(edge){v,head[u],w};
    	head[u]=cnt;
    	a[++cnt]=(edge){u,head[v],0};
    	head[v]=cnt;
    }
    bool bfs()
    {
    	memset(dep,0,sizeof(dep));
    	dep[s]=1;Q.push(s);
    	while (!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for (int e=head[u];e;e=a[e].next)
    			if (a[e].w&&!dep[a[e].to])
    				dep[a[e].to]=dep[u]+1,Q.push(a[e].to);
    	}
    	return dep[t];
    }
    int dfs(int u,int flow)
    {
    	if (u==t)
    		return flow;
    	for (int &e=cur[u];e;e=a[e].next)
    		if (a[e].w&&dep[a[e].to]==dep[u]+1)
    		{
    			int temp=dfs(a[e].to,min(flow,a[e].w));
    			if (temp) {a[e].w-=temp;a[e^1].w+=temp;return temp;}
    		}
    	return 0;
    }
    int Dinic()
    {
    	int res=0;
    	while (bfs())
    	{
    		for (int i=t;i;i--) cur[i]=head[i];
    		while (int temp=dfs(s,inf)) res+=temp;
    	}
    	return res;
    }
    int check(int mid)
    {
    	memset(head,0,sizeof(head));cnt=1;
    	for (int i=1;i<=n;i++)
    	{
    		link(s,i,mid);
    		link(i+3*n,t,mid);
    		link(i,i+n,k);
    		link(i+2*n,i+3*n,k);
    	}
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=n;j++)
    			if (g[i][j]=='Y')
    				link(i,j+3*n,1);
    			else
    				link(i+n,j+2*n,1);
    	return Dinic();
    }
    int main()
    {
    	n=gi();k=gi();s=4*n+1;t=s+1;
    	for (int i=1;i<=n;i++)
    		scanf("%s",g[i]+1);
    	int l=0,r=n;
    	while (l<r)
    	{
    		int mid=l+r+1>>1;
    		if (check(mid)==mid*n) l=mid;
    		else r=mid-1;
    	}
    	printf("%d
    ",l);
    	return 0;
    }
    
  • 相关阅读:
    [2017-7-28]Android Learning Day7
    Codeforces Round #402 (Div. 2) D. String Game
    POJ2411 铺地砖 Mondriaan's Dream
    《大型网站系统架构的演化》
    Nginx 引入线程池,提升 9 倍性能
    《淘宝消息中间件概述》2015-07-11
    主从复制源代码分析
    深入剖析Redis主从复制
    主从复制配置
    Redis启动多端口、运行多实例
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8192456.html
Copyright © 2020-2023  润新知