bzoj 1305 dance跳舞

网络流。

首先二分答案,问题转化为x首舞曲是否可行。

考虑建图,对每个人建立三个点,分别表示全体,喜欢和不喜欢。

源点向每个男生全体点连一条容量为x的边。

每个男生整体点向喜欢点连一条容量为正无穷的边,向不喜欢点连一条容量为k的边。

每个男生喜欢点向所有他喜欢的女生的喜欢点连一条容量为一的边,不喜欢点向所有他不喜欢的女生的不喜欢点连一条容量为一的边。

每个女生喜欢点向整体点连一条容量为正无穷的边,不喜欢点向整体点连一条容量为k的边。

每个女生整体点向汇点连一条容量为x的边。

check即为判断最大流是否等于n*x。

本题中流量的定义为舞曲数,整体点向源汇点的连边保证了每一轮正好配成n对,如某一轮中存在一个女生对应多个男生,最终最大流就会减小。

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int dian=305;
const int bian=40005;
const int INF=0x3f3f3f3f;
int n,k,tot;
int S,T;
int h[dian],nxt[bian],ver[bian],val[bian],ch[dian];
char map[55][55];
void add(int aa,int bb,int cc){
    tot++;ver[tot]=bb;val[tot]=cc;nxt[tot]=h[aa];h[aa]=tot;
    tot++;ver[tot]=aa;val[tot]=0;nxt[tot]=h[bb];h[bb]=tot;
}
int bh(int aa,int p,int ok){
    return (aa-1)*3+p+ok*3*n;
}
bool tell(){
    memset(ch,-1,sizeof(ch));
    queue<int>q;
    q.push(S);
    ch[S]=0;
    while(!q.empty()){
        int t=q.front();
        q.pop();
        for(int i=h[t];i;i=nxt[i])
            if(ch[ver[i]]==-1&&val[i]){
                q.push(ver[i]);
                ch[ver[i]]=ch[t]+1;
            }
    }
    return ch[T]!=-1;
}
int zeng(int a,int b){
    if(a==T)
        return b;
    int r=0;
    for(int i=h[a];i&&b>r;i=nxt[i])
        if(ch[ver[i]]==ch[a]+1&&val[i]){
            int t=zeng(ver[i],min(b-r,val[i]));
            val[i]-=t,r+=t,val[i^1]+=t;
        }
    if(!r)
        ch[a]=-1;
    return r;
}
int dinic(){
    int r=0,t;
    while(tell())
        while(t=zeng(S,INF))
            r+=t;
    return r;
}
bool check(int mid){
    memset(nxt,0,sizeof(nxt));
    memset(h,0,sizeof(h));
    tot=1;
    for(int i=1;i<=n;i++){
        add(S,bh(i,1,0),mid);
        add(bh(i,1,1),T,mid);
        add(bh(i,1,0),bh(i,2,0),INF);
        add(bh(i,1,0),bh(i,3,0),k);
        add(bh(i,2,1),bh(i,1,1),INF);
        add(bh(i,3,1),bh(i,1,1),k);
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            if(map[i][j]==‘Y‘)
                add(bh(i,2,0),bh(j,2,1),1);
            else
                add(bh(i,3,0),bh(j,3,1),1);
        }
    if(dinic()==n*mid)
        return true;
    return false;
}
int bin(int l,int r){
    int mid;
    while(l<r){
        mid=(l+r+1)>>1;
        if(check(mid))
            l=mid;
        else
            r=mid-1;
    }
    return l;
}
int main(){
    scanf("%d%d",&n,&k);
    S=6*n+1,T=6*n+2;
    for(int i=1;i<=n;i++)
        scanf("%s",map[i]+1);
    printf("%d",bin(0,50));
    return 0;
}
时间: 2024-08-10 19:19:02

bzoj 1305 dance跳舞的相关文章

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

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

【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 二分+網絡流判定

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

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 向汇点连流量

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

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

bzoj1305【CQOI2009】dance 跳舞

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

[CQOI2009][BZOJ1305] dance跳舞

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

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