并不对劲的bzoj1305: [CQOI2009]dance跳舞

传送门->

又是陈年老坑。 

听上去不知道从何下【手】?那要是把题目换成“判断这些人能否条x支舞”呢?

这样就变成了一个网络流可以解决的问题,只要把每个人拆成喜欢和不喜欢两点,每个人两点总流量不超过x,喜欢的人之间的连边是x,不喜欢的人之间连边为k,最后通过判断是否每个人总流量流满就行。

会发现x越大,越难以流满,有单调性,那就可以二分了。

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define re register
#define maxn 510
#define maxm 500010
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(isdigit(ch)==0 && ch!='-')ch=getchar();
    if(ch=='-')f=-1,ch=getchar();
    while(isdigit(ch))x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(int x)
{
    int f=0;char ch[20];
    if(!x){puts("0");return;}
    if(x<0){putchar('-');x=-x;}
    while(x)ch[++f]=x%10+'0',x/=10;
    while(f)putchar(ch[f--]);
    putchar('\n');
}
int n,K,fir[maxn],nxt[maxm],v[maxm],fl[maxm],dis[maxn],maxflow,cnt,l,r,ans,s,t,inf[3];
char yes[60][60];
queue<int >q;
void ade(int u1,int v1,int fl1)
{
	v[cnt]=v1,fl[cnt]=fl1,nxt[cnt]=fir[u1],fir[u1]=cnt++;
	v[cnt]=u1,fl[cnt]=0,nxt[cnt]=fir[v1],fir[v1]=cnt++;
}
void reset(){memset(fir,-1,sizeof(fir)),maxflow=cnt=0;}
int bfs()
{
	memset(dis,-1,sizeof(dis));
	dis[t]=0;q.push(t);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		for(int k=fir[u];k!=-1;k=nxt[k])
		{
			int vv=v[k];
			if(fl[k^1]&&dis[vv]==-1)
			{
				dis[vv]=dis[u]+1;
				q.push(vv);
			}
		}
	}
	return dis[s]==-1?0:1;
}
int dfs(int u,int nowflow)
{
	if(u==t||!nowflow)return nowflow;
	int tmp,sum=0;
	for(int k=fir[u];k!=-1;k=nxt[k])
	{
		if(!nowflow)break;
		int vv=v[k];
		if(dis[vv]+1==dis[u]&&fl[k]&&(tmp=dfs(vv,min(fl[k],nowflow)))>0)
			fl[k]-=tmp,fl[k^1]+=tmp,nowflow-=tmp,sum+=tmp;		
	}
	return sum;
} 
int check(int tim)
{
	s=0,t=n*4+1;
	rep(i,1,n)ade(s,i,tim),ade(i,i+n,K),ade(i+n*2,t,tim),ade(i+n*3,i+n*2,K);
	rep(i,1,n)
	    rep(j,1,n)
	    {
	    	if(yes[i][j]=='Y')ade(i,j+n*2,1);
	    	else ade(i+n,j+n*3,1);
	    }
	while(bfs())maxflow+=dfs(s,inf[0]);	
	return (maxflow==n*tim);
}
int main()
{
    memset(inf,0x7f,sizeof(inf));
    n=read(),K=read();
    rep(i,1,n){scanf("%s",yes[i]+1);}
    l=0,r=n;
    while(l<=r)
    {
    	reset();
    	int mid=(l+r)>>1;
    	if(check(mid))ans=mid,l=mid+1;
    	else r=mid-1;
    }
    write(ans);
	return 0;
}

  

posted @ 2018-08-17 14:15  echo6342  阅读(172)  评论(0编辑  收藏  举报