【CQOI2009】跳舞 网络流

题目描述

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

数据范围

【CQOI2009】跳舞 网络流_第1张图片

样例输入

【输入1】
3 0
YYY
YYY
YYY
【输入2】
3 0
YYY
YYN
YNY
【输入3】
2 0
YN
YN
【输入4】
2 1
YN
YN

样例输出

【输出1】3
【输出2】2
【输出3】0
【输出4】1

解题思路

  不知为何,我们学校OJ把这道题rejudge(应该是吧)了,数据也由10组增加成了20组,我原来AC了的代码也wrong了。。。于是从写此题
  建图: ①每个点拆成2个点,加上源点汇点,也就是4n+2个点。
      ②起点向男生的第一个点连边,权值为k(二分用)
      ③女生的第二个点向汇点连边,权值为k(二分用)
      ④如果男生A,与女生B互相喜欢,则男生的第一个点向女生的第二个点连边,否则男生的第二个点向女生的第一个点连边。(权值为1)
      ⑤男生的第一个点向男生的第二个点连边,权值为k(题目中的k)
      ⑥女生的第一个点向女生的第二个点连边,权值为k(题目中的k)
      ⑦然后二分k,如果满流(流量为n*k(k为二分的k))则成立。
      ⑧答案就是k(二分的k。。)
  其实我是直接用残余网络跑的,只需判断流量是否为n就行其实感觉与二分并没有什么区别,反正n都这么小

代码

#include 
#include 
#include 
#include 
#include 
#include 
#define Maxn 233333
#define Maxe 233333
using namespace std;
inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
int S,T,N,cnt=0,dis[Maxn],GAP[Maxn],h[Maxn],Map[505][505];
struct node{int to,next,v,pair;}e[Maxe];
void AddEdge(int x,int y,int v,int pair){e[cnt]=(node){y,h[x],v,pair};h[x]=cnt;}
void AddEdge(int x,int y,int v){AddEdge(x,y,v,++cnt+1);AddEdge(y,x,0,++cnt-1);}
int SAP(int x,int Maxflow){
    if(x==T)return Maxflow;
    int tmp=Maxflow;
    for(int p=h[x];p;p=e[p].next){
        int y=e[p].to;
        int flow=min(tmp,e[p].v);
        if(flow&&dis[x]==dis[y]+1){
            int ret=SAP(y,flow);
            tmp-=ret;
            e[p].v-=ret;
            e[e[p].pair].v+=ret;
            if(!tmp||dis[S]==N)return Maxflow-tmp;
        }
    }
    if(--GAP[dis[x]]==0)dis[S]=N;
    else GAP[++dis[x]]++;
    return Maxflow-tmp;
}
int SAP(){
    memset(GAP,0,sizeof(GAP));
    memset(dis,0,sizeof(dis));
    GAP[0]=N;
    long long Ans=0;
    while(dis[S]1<<30);
    return Ans;
}
int n,k;
void Init(){
    n=Getint();k=Getint();
    S=0,T=4*n+1,N=T+1;
    for(int i=1;i<=n;i++){
        string s;
        cin>>s;
        for(int j=1;j<=n;j++)
            Map[i][j]=s[j-1]=='Y';
    }
}
int main(){
    Init();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(Map[i][j])
                AddEdge(i,j+n*3,1);
            else
                AddEdge(i+n,j+n*2,1);
    for(int i=1;i<=n;i++)AddEdge(i,i+n,k);
    for(int i=1;i<=n;i++)AddEdge(i+n*2,i+n*3,k);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)AddEdge(S,j,1);
        for(int j=1;j<=n;j++)AddEdge(j+n*3,T,1);
        int t;
        if(SAP()!=n){
            cout<1;
            return 0;
        }
    }
    cout<return 0;
}

转载于:https://www.cnblogs.com/Cedric341561/p/6811023.html

你可能感兴趣的:(【CQOI2009】跳舞 网络流)