[BZOJ1305/Luogu3153][CQOI2009]dance跳舞(网络流)

发布于 2018-02-26  58 次阅读


本文章由SYCstudio或本站其它作者所有,严禁转载,转载必究

本文链接地址:[BZOJ1305/Luogu3153][CQOI2009]dance跳舞(网络流)

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

Http

BZOJ
Luogu

Tag

网络流

解决思路

对于每一个人拆成两个点,一个点表示喜欢的,另一个点表示不喜欢的,若两个人互相喜欢,那么就连接两个表示的点,否则连接两个表示不喜欢的点。然后,由于要求一个人最多只与\(k\)个不喜欢的人跳,那么一个人拆成的两个点之间的容量就为\(k\)。那么接下来就是枚举轮数,每一次修改对应的从源点连出的边和到汇点的边。若当前最大流等于人数乘以轮数,则可以继续,否则轮数--

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

#define ll long long
#define mem(Arr,x) memset(Arr,x,sizeof(Arr))

const int maxN=51*4;
const int maxM=maxN*100;
const int inf=2147483647;

class Edge
{
public:
    int v,flow;
};

int n,K,S,T;
int edgecnt=-1,Head[maxN],Next[maxM];
Edge E[maxM];
char Input[maxN];
int Depth[maxN],Queue[maxN],cur[maxN];

void Add_Edge(int u,int v,int flow);
bool Bfs();
int dfs(int u,int flow);

int main()
{
    mem(Head,-1);
    ios::sync_with_stdio(false);
    cin>>n>>K;S=n*4+1;T=S+1;//建图
    for (int i=1;i<=n;i++) Add_Edge(S,i,0),Add_Edge(i,i+n+n,K);
    for (int i=1;i<=n;i++) Add_Edge(i+n,T,0),Add_Edge(i+n+n+n,i+n,K);
    for (int i=1;i<=n;i++)
    {
        cin>>(Input+1);
        for (int j=1;j<=n;j++)
            if (Input[j]=='Y') Add_Edge(i,j+n,1);
            else Add_Edge(i+n+n,j+n+n+n,1);
    }
    int round=0,mxflow=0;
    do//枚举轮数
    {
        while (Bfs())//求最大流
        {
            for (int i=1;i<=T;i++) cur[i]=Head[i];
            while (int di=dfs(S,inf)) mxflow+=di;
        }
        if (mxflow!=round*n) break;
        round++;
        for (int i=Head[S];i!=-1;i=Next[i])
            if ((E[i].v>=1)&&(E[i].v<=n)) E[i].flow++;
        for (int i=Head[T];i!=-1;i=Next[i])
            if ((E[i].v>=n+1)&&(E[i].v<=n+n)) E[i^1].flow++;
    }
    while (1);
    printf("%d\n",round-1);
    return 0;
}

void Add_Edge(int u,int v,int flow)
{
    edgecnt++;Next[edgecnt]=Head[u];Head[u]=edgecnt;
    E[edgecnt].v=v;E[edgecnt].flow=flow;
    edgecnt++;Next[edgecnt]=Head[v];Head[v]=edgecnt;
    E[edgecnt].v=u;E[edgecnt].flow=0;
    return;
}

bool Bfs()
{
    mem(Depth,-1);
    int h=1,t=0;Queue[1]=S;Depth[S]=1;
    do
    {
        int u=Queue[++t];
        for (int i=Head[u];i!=-1;i=Next[i])
            if ((Depth[E[i].v]==-1)&&(E[i].flow>0))
                Depth[Queue[++h]=E[i].v]=Depth[u]+1;
    }
    while (h!=t);
    if (Depth[T]!=-1) return 1;
    return 0;
}

int dfs(int u,int flow)
{
    if (u==T) return flow;
    for (int &i=cur[u];i!=-1;i=Next[i])
        if ((E[i].flow>0)&&(Depth[E[i].v]==Depth[u]+1))
        {
            int di=dfs(E[i].v,min(flow,E[i].flow));
            if (di)
            {
                E[i].flow-=di;
                E[i^1].flow+=di;
                return di;
            }
        }
    return 0;
}

本文章由SYCstudio或本站其它作者所有,严禁转载,转载必究

本文链接地址:[BZOJ1305/Luogu3153][CQOI2009]dance跳舞(网络流)


HNCJ OIer 一枚