洛谷_2055 假期的宿舍

本文介绍了一种使用最大流算法解决学生住宿分配问题的方法。通过构建合适的图模型,并运用最大流算法,可以判断是否有足够的床位供所有学生使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

有几个同学要来盼望在学校里的同学,他们希望他们和学校里的同学都有床睡,其中一个人只能睡他认识的人的床或自己的床。现在给出每个同学是否在校生和是否回家的情况,以及它们认识的情况,求出它们能否全部人都有床睡。

思路

这道题构好图然后跑一边最大流。让有床的人和汇点连接,需要床的人和源点连接,然后他们如果互相认识就让他们连接。

代码

#include<cstdio>
#include<cstring>
#include<queue>
#define min(a,b) a<b?a:b
using namespace std;
int tot,t,n,S,T,x,head[101],d[101],f,ans,sum;bool a[51];
struct node{
    int to,next,v;
}e[1001];
void add(int x,int y)
{
    e[++tot].to=y;e[tot].next=head[x];e[tot].v=1;
    head[x]=tot;
    e[++tot].to=x;e[tot].next=head[y];e[tot].v=0;
    head[y]=tot;
}
bool bfs()
{
    memset(d,0,sizeof(d));
    int v;
    queue<int>q;
    d[S]=1;q.push(S);
    while (q.size())
    {
        v=q.front();q.pop();
        for (int i=head[v];i!=-1;i=e[i].next)
        {
            int y=e[i].to;
            if (d[y]==0&&e[i].v)
            {
                d[y]=d[v]+1;
                q.push(y);
                if (y==T) return 1;
            }
        }
    }
    return 0;
}
int dfs(int k,int flow)
{
    if (k==T) return flow;
    int rest=0,w;
    for (int i=head[k];i!=-1;i=e[i].next)
    {
        if (e[i].v&&d[k]+1==d[e[i].to])
        {
            w=dfs(e[i].to,min(e[i].v,flow-rest));
            if (!w) d[e[i].to]=0;
            e[i].v-=w;
            e[i^1].v+=w;
            rest+=w;
        }
    }
    return rest;
}
int main()
{
    scanf("%d",&t);
    while (t--)
    {
        memset(head,-1,sizeof(head));
        ans=sum=0;
        tot=1;
        scanf("%d",&n);
        S=0;T=2*n+1;
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if (a[i]) add(i+n,T);//在校生有床就和汇点连接
        }
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            if(!x||!a[i]) 
            {
                add(S,i);//需要床的
                ans++;//记录需要床的人数
            }
        }
        for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=n;j++)
            {
                scanf("%d",&x);
                if (x||i==j) add(i,j+n);//相互认识还有睡自己床的
            }
        }
        while (bfs())
            while (f=dfs(S,2147483647)) sum+=f;//求出最大流
        if (sum==ans) printf("^_^\n");//判断是否够床
        else printf("T_T\n");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值