bzoj1305: [CQOI2009]dance跳舞(二分答案+网络流)

1305: [CQOI2009]dance跳舞

题目:传送门

题解:

   一眼网络流基础建模...然后就GG了

   二分答案+拆点建边+最大流判断:
   把男女生拆为男1,男2,女1,女2

   1、男1和男2还有女1和女2之间连边,流量为约束条件k

   2、st连男1,女2连ed,流量为二分的mid

   3、如果男生i喜欢女生j,就将男1与女2相连(不在约束条件内)

   4、如果不喜欢,就将男2与女1相连(在约束条件内)

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<algorithm>
  6 using namespace std;
  7 char ss[55][55];
  8 struct node
  9 {
 10     int x,y,c,next,other;
 11 }a[2110000];int len,last[1110000];
 12 int st,ed,head,tail,n,k;
 13 void ins(int x,int y,int c)
 14 {
 15     int k1,k2;
 16     k1=++len;
 17     a[len].x=x;a[len].y=y;a[len].c=c;
 18     a[len].next=last[x];last[x]=len;
 19
 20     k2=++len;
 21     a[len].x=y;a[len].y=x;a[len].c=0;
 22     a[len].next=last[y];last[y]=len;
 23
 24     a[k1].other=k2;
 25     a[k2].other=k1;
 26 }
 27 int h[1110000],list[1110000];
 28 bool bt_h()
 29 {
 30     memset(h,0,sizeof(h));h[st]=1;
 31     head=1;tail=2;list[1]=st;
 32     while(head!=tail)
 33     {
 34         int x=list[head];
 35         for(int k=last[x];k;k=a[k].next)
 36         {
 37             int y=a[k].y;
 38             if(h[y]==0 && a[k].c)
 39             {
 40                 h[y]=h[x]+1;
 41                 list[tail++]=y;
 42             }
 43         }
 44         head++;
 45     }
 46     if(h[ed])return true;
 47     return false;
 48 }
 49 int find_flow(int x,int flow)
 50 {
 51     if(x==ed)return flow;
 52     int t,s=0;
 53     for(int k=last[x];k;k=a[k].next)
 54     {
 55         int y=a[k].y;
 56         if(h[y]==(h[x]+1) && a[k].c && s<flow)
 57         {
 58             s+=t=find_flow(y,min(a[k].c,flow-s));
 59             a[k].c-=t;a[a[k].other].c+=t;
 60         }
 61     }
 62     if(s==0)h[x]=0;
 63     return s;
 64 }
 65 int mid,l,r;
 66 int s1[55],s2[55];
 67 void build(int cc)
 68 {
 69     len=0;memset(last,0,sizeof(last));
 70     st=4*n+1;ed=st+1;
 71     for(int i=1;i<=n;i++)ins(st,i,cc);
 72     for(int i=1;i<=n;i++)ins(i+n*3,ed,cc);
 73     for(int i=1;i<=n;i++)ins(i,i+2*n,k);
 74     for(int i=1;i<=n;i++)ins(i+n,i+n*3,k);
 75     /*for(int i=1;i<=n;i++)
 76     {
 77         ins(st,i,cc);
 78         ins(i,i+n*2,s1[i]+k);//男1-->男2
 79     }
 80     for(int j=1;j<=n;j++)
 81     {
 82         ins(j+n*3,ed,cc);
 83         ins(j+n,j+n*3,s2[j]+k);//女1-->女2
 84     }*/
 85     for(int i=1;i<=n;i++)//男2-->女1
 86         for(int j=1;j<=n;j++)
 87         {
 88             if(ss[i][j]==‘Y‘)ins(i,j+n*3,1);
 89             else ins(i+n*2,j+n,1);
 90         }
 91 }
 92 bool check(int cnt)
 93 {
 94     build(cnt);
 95     int ans=0;
 96     while(bt_h())
 97         ans+=find_flow(st,999999999);
 98     if(ans==n*cnt)return true;
 99     return false;
100 }
101 int main()
102 {
103     scanf("%d%d",&n,&k);
104     for(int i=1;i<=n;i++)scanf("%s",ss[i]+1);
105     l=1;r=n;int sum=0;
106     while(l<=r)
107     {
108         mid=(l+r)/2;
109         if(check(mid))
110         {
111             l=mid+1;
112             sum=mid;
113         }
114         else r=mid-1;
115     }
116     printf("%d\n",sum);
117     return 0;
118 }

原文地址:https://www.cnblogs.com/CHerish_OI/p/8505105.html

时间: 2024-08-28 09:55:28

bzoj1305: [CQOI2009]dance跳舞(二分答案+网络流)的相关文章

BZOJ 1305 CQOI2009 dance跳舞 二分答案+最大流

题目大意:给定n个男生和n个女生,一些互相喜欢而一些不.举行几次舞会,每次舞会要配成n对.不能有同样的组合出现.每一个人仅仅能与不喜欢的人跳k次舞,求最多举行几次舞会 将一个人拆成两个点.点1向点2连一条流量为k的边.两个人若互相喜欢则点1之间连边,不喜欢则点2之间连边 对于每个要验证的x值 将每个人的点1向源或汇连一条流量为x的边 然后二分答案跑最大流就可以 #include<cstdio> #include<cstring> #include<iostream> #

BZOJ-1305: [CQOI2009]dance跳舞(最大流 增加超级源汇+分裂点+二分 水题)

1305: [CQOI2009]dance跳舞 Time Limit: 5 Sec  Memory Limit: 162 MB Description 一次舞会有n个男孩和n个女孩.每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞.每个男孩都不会和同一个女孩跳两首(或更多)舞曲.有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“单向喜欢”).每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞.给出每对男孩女孩是否相互喜欢的信息,舞会最多能有几首舞曲? Inpu

bzoj千题计划130:bzoj1305: [CQOI2009]dance跳舞

http://www.lydsy.com/JudgeOnline/problem.php?id=1305 每个人拆为喜欢(yes)和不喜欢(no)两个点 二分答案 1.每两个人之间只能跳一次 喜欢则 男yes i 向 女yes j 连流量为1的边 不喜欢则 男no i 向 女no j 连流量为1的边 2.最多与k个不喜欢的人跳 男yes i 向 男no i 连流量为 k的边 女no j 向 女yes j 连流量为k 的边 3. 源点向 男yes i 连流量mid 的边 女yes j 向汇点连流量

【二分答案】【最大流】bzoj1305 [CQOI2009]dance跳舞

http://hzwer.com/1986.html #include<cstdio> #include<algorithm> #include<queue> #include<cstring> using namespace std; #define INF 2147483647 #define N 51 int n,m; char a[N][N]; queue<int>q; int S,T,nn; int first[(N<<2)

bzoj1305: [CQOI2009]dance跳舞

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

【BZOJ 1305】 [CQOI2009]dance跳舞

1305: [CQOI2009]dance跳舞 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 1586  Solved: 666 [Submit][Status] Description 一次舞会有n个男孩和n个女孩.每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞.每个男孩都不会和同一个女孩跳两首(或更多)舞曲.有一些男孩女孩相互喜欢,而其他相互不喜欢(不会"单向喜欢").每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只

BZOJ 1305: [CQOI2009]dance跳舞( 最大流 )

云神代码很短...0 ms过的...看了代码 , 大概是贪心... orz 我不会证 数据这么小乱搞就可以了吧... ←_← 这道题网络流还是可以写的... 既然限制了最多只能和 k 个不喜欢的人dance ,  那么就把每个人拆成 a , b 两个点 . 限制完了之后 , 因为 n <= 50 , 我们可以直接从从小到大枚举 , 一个一个增广 . 具体建图 : boy_a( i ) -> boy_b( i ) ( cap : k ) , girl_b( i ) -> girl_a( i

AC日记——[CQOI2009]DANCE跳舞 洛谷 P3153

[CQOI2009]DANCE跳舞 思路: 二分+最大流: 代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 505 #define maxm 30005 #define INF 0x3f3f3f3f int head[maxn],E[maxm],V[maxm],F[maxm],

bzoj 1305: [CQOI2009]dance跳舞

题目链接 bzoj 1305: [CQOI2009]dance跳舞 题解 男,女生拆点A1A2,B1B2,拆成两点间分别连容量为K的边,限制与不喜欢的人跳舞的数量 A1连接源点容量为x,B1连接汇点容量为x,x即为歌曲数目 对与相互喜欢的男女直在A1,B1间接连容量为1的边 对于相互不喜欢A2练到B2,容量为1 二分x的大小,每次重新构图,判断该图是否满流,慢流则说明该曲目可行 代码 #include<queue> #include<cstdio> #include<cstr