洛谷_2055 假期的宿舍

题意

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

思路

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

代码

#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");
    }
}

猜你喜欢

转载自blog.csdn.net/ssl_hzb/article/details/80759389