BZOJ-1433 假期的宿舍 最大流+基础建图

网络流练习ing。。

1433: [ZJOI2009]假期的宿舍
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 1748 Solved: 765
[Submit][Status][Discuss]

Description
这里写图片描述

Input
这里写图片描述

Output
这里写图片描述

Sample Input
1
3
1 1 0
0 1 0
0 1 1
1 0 0
1 0 0

**Sample Outpu**t
ˆ-ˆ

HINT
对于30% 的数据满足1 ≤ n ≤ 12。
对于100% 的数据满足1 ≤ n ≤ 50,1 ≤ T ≤ 20。

基础建图:
超级源连向所有在校生(有床位的人);所有在校生且不回家的,与所有非在校生的与超级源相连;每个点分成两个i与i',如果i和j认识连i与j';边权全部为1
最大流即为答案。

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define M 1000010
struct data{
     int  to,next,v;
}edge[M];
int head[M],cnt=1;
int dis[M];
int q[M],h,t;
int c,n,ans,num;
int zx[60],know[60][60],hj[60];
 //zx【】是否在校,know【】【】是否认识,hj【】是否回家

void add(int u,int v,int w)
{
    cnt++;
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt;
    edge[cnt].v=w;
}

void make()//超级源为0,超级汇为2*n+1
{
    cnt=1;  memset(head,0,sizeof(head));
    num=0;
    for (int i=1; i<=n; i++)
        for (int j=1; j<=n; j++)
            if (know[i][j]==1)
                {
                    add(i,j+n,1);
                    add(j+n,i,0);
                }
    for (int i=1; i<=n; i++)
        {
            if (zx[i]==1)
                {
                    add(0,i,1);
                    add(i,0,0);
                }
            if ((zx[i]==1 && hj[i]==0) || (zx[i]==0))
                {
                    add(i+n,2*n+1,1);
                    add(2*n+1,i+n,0);
                    num++;//需要床位数
                }
        }
}

bool bfs()
{
    memset(dis,-1,sizeof(dis));
    q[1]=0; dis[0]=1;
    h=0; t=1;
    while (h<t)
        {
            int j=q[++h],i=head[j];
            while (i)
                {
                    if (edge[i].v>0 && dis[edge[i].to]<0)
                        {
                            dis[edge[i].to]=dis[j]+1;
                            q[++t]=edge[i].to;
                        }
                    i=edge[i].next;
                }
        }
    if (dis[2*n+1]>0)
        return true;
    else
        return false;   
}

int dfs(int loc,int low)
{
    int flow=0;
    if (loc==2*n+1) return low;
    int i=head[loc];
    while (i)
        {
            if (edge[i].v>0 && dis[edge[i].to]==dis[loc]+1 && (flow=dfs(edge[i].to,min(low,edge[i].v))))
                {
                    edge[i].v-=flow;
                    edge[i^1].v+=flow;
                    return flow;
                }
            i=edge[i].next;
        }
    return 0;
}

int main()
{
    scanf("%d",&c);
    while (c--)
        {
            scanf("%d",&n);
            memset(zx,0,sizeof(zx));
            memset(hj,0,sizeof(hj));
            memset(know,0,sizeof(know));
            for (int i=1; i<=n; i++)
                scanf("%d",&zx[i]);
            for (int i=1; i<=n; i++)
                scanf("%d",&hj[i]);
            for (int i=1; i<=n; i++)
                for (int j=1; j<=n; j++)
                    scanf("%d",&know[i][j]);
            for (int i=1; i<=n; i++)
                know[i][i]=1;//由题意自己和自己在读入时为不能睡,但实际可以,修改。
            make();
            ans=0;
            while (bfs())
                {
                    int now=0;
                    while ((now=dfs(0,0x7fffffff)))
                        ans+=now;
                }
            if  (num==ans)
                puts("^_^");
            else
                puts("T_T");        
        }
    return 0;
}
posted @ 2016-01-05 20:50  DaD3zZ  阅读(169)  评论(0编辑  收藏  举报