首页 写随笔

cdcq(本博客废弃!现用博客:https://www.cnblogs.com/cdcq/)

本博客废弃!现用博客:https://www.cnblogs.com/cdcq/

导航

【BZOJ1305】【CQOI2009】 dance跳舞

看menci的博客点出二分的思路然后做出来,menci太强辣

原题:

一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“单向喜欢”)。每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞。给出每对男孩女孩是否相互喜欢的信息,舞会最多能有几首舞曲?

N<=50 K<=30

 

看榜上的都是0MS,这是什么神奇的做法

先看menci的博客发现这道题,知道是网络流,想了一段时间无果,回menci的博客看了一眼,然后发现两个字

"二分"

然后思路就想出来了,二分答案,根据答案建图然后验证是否能跑到满流

具体建图方法就很简答了,相互喜欢的男女权值为1,每个男女要额外一个点来保证和不喜欢的人的限制,本来的点和额外的点中间权值为k,两个不喜欢的男女之间额外的点权值为1,源到男,女到汇权值为二分的答案

如果能跑到满流就说明答案和法

另外有一点需要注意就是二分的下线要从0开始,因为可能会无解

二分也是转换问题很关键的方式,以后想题还要尽量考虑一下

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<vector>
 7 using namespace std;
 8 const int oo=168430090;
 9 int rd(){int z=0,mk=1;  char ch=getchar();
10     while(ch<'0'||ch>'9'){if(ch=='-')mk=-1;  ch=getchar();}
11     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
12     return z*mk;
13 }
14 struct ddd{int y,v,re;};  vector <ddd> e[210];
15 inline void ist(int x,int y,int z){
16     e[x].push_back((ddd){y,z,e[y].size()});
17     e[y].push_back((ddd){x,0,e[x].size()-1});
18 }
19 int n,m;  int s,t;  int n2,n3,n4;
20 char a[60][60];
21 int lvl[210];
22 int q[210],hd=0;
23 void clear(){  for(int i=s;i<=t;++i)  e[i].clear();}
24 bool gtlvl(){
25     memset(lvl,0,sizeof(lvl));
26     q[hd=1]=s,lvl[s]=1;
27     int x,sz;
28     for(int k=1;k<=hd;++k){
29         x=q[k],sz=e[x].size();
30         for(int i=0;i<sz;++i)if(e[x][i].v && !lvl[e[x][i].y])
31             lvl[e[x][i].y]=lvl[x]+1,q[++hd]=e[x][i].y;
32     }
33     return lvl[t];
34 }
35 int agmt(int x,int y){
36     if(x==t)  return y;
37     int mxflw=0,flw,sz=e[x].size();
38     for(int i=0;i<sz && mxflw<y;++i)if(lvl[e[x][i].y]==lvl[x]+1 && e[x][i].v)
39         if(flw=agmt(e[x][i].y,min(y-mxflw,e[x][i].v))){
40             mxflw+=flw;
41             e[x][i].v-=flw,e[e[x][i].y][e[x][i].re].v+=flw;
42         }
43     if(!mxflw)  lvl[x]=0;
44     return mxflw;
45 }
46 int dnc(){
47     int bwl=0,flw;
48     while(gtlvl())while(flw=agmt(s,oo))  bwl+=flw;
49     return bwl;
50 }
51 bool chck(int x){
52     clear();
53     for(int i=1;i<=n;++i){
54         for(int j=1;j<=n;++j){
55             if(a[i][j]=='Y')  ist(i,j+n3,1);
56             else  ist(i+n,j+n2,1);
57         }
58         ist(i,i+n,m),ist(i+n2,i+n3,m);
59         ist(s,i,x),ist(i+n3,t,x);
60     }
61     return dnc()==x*n;
62 }
63 int bnrsch(){
64     int l=0,r=n,md;
65     while(l+1<r){  md=(l+r)>>1;  (chck(md)?l:r)=md;}
66     return chck(r)?r:l;
67 }
68 int main(){//freopen("ddd.in","r",stdin);
69     cin>>n>>m;  n2=n*2,n3=n*3,n4=n*4;  s=0,t=n4+1;
70     /*for(int i=1;i<=n;++i){
71         scanf("%s",s+1);
72         for(int j=1;j<=n;++j){
73             if(s[j]=='Y')  ist(i,j+3n,1);
74             else  ist(i+n,j+2n,1);
75         }
76         ist(i,i+n,k),ist(i+2n,i+3n,k);*/
77     for(int i=1;i<=n;++i)  scanf("%s",a[i]+1);
78     cout<<bnrsch()<<endl;
79     return 0;
80 }
View Code

 

posted on 2017-02-23 21:45  cdcq_old  阅读(191)  评论(0编辑  收藏  举报