bzoj1433 [ZJOI2009]假期的宿舍(最大流/二分图最大匹配)

来源:互联网 发布:mac相册导入iphone 编辑:程序博客网 时间:2024/06/05 05:40

S向所有需要床的人建边,所有床向T建边,i认识j,i向j的床建边,每个人向自己的床建边,跑dinic,看是否所有需要床的人都有床了。为什么要把人和床分开建呢?因为a认识b,b认识c,a不认识c的话,a并不能睡在c的床上。如果只建一个人,就会出现问题。

#include <bits/stdc++.h>using namespace std;#define ll long long#define N 150#define inf 0x3f3f3f3finline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}int tst,n,tot=0,num=1,h[N],lev[N],T;bool f[N];//f->1 在校 struct edge{    int to,next,val;}data[N*N<<1];inline void add(int x,int y,int val){    data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val;    data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].val=0;}inline bool bfs(){    queue<int>q;memset(lev,0,sizeof(lev));    q.push(0);lev[0]=1;    while(!q.empty()){        int x=q.front();q.pop();        for(int i=h[x];i;i=data[i].next){            int y=data[i].to;if(lev[y]||!data[i].val) continue;            lev[y]=lev[x]+1;q.push(y);        }    }return lev[T];}int dinic(int x,int low){    if(x==T) return low;int tmp=low;    for(int i=h[x];i;i=data[i].next){        int y=data[i].to;if(lev[y]!=lev[x]+1||!data[i].val) continue;        int res=dinic(y,min(low,data[i].val));        if(!res) lev[y]=0;tmp-=res;data[i].val-=res;data[i^1].val+=res;        if(!tmp) return low;    }return low-tmp;}int main(){//  freopen("a.in","r",stdin);    tst=read();    while(tst--){        n=read();num=1;memset(h,0,sizeof(h));tot=0;T=n+n+1;        for(int i=1;i<=n;++i){            f[i]=read();if(f[i]) add(i+n,T,1);if(!f[i]) add(0,i,1),++tot;        }for(int i=1;i<=n;++i){            int x=read();if(!f[i]) continue;if(!x) add(0,i,1),++tot;        }for(int i=1;i<=n;++i)            for(int j=1;j<=n;++j){                int x=read();if(x||i==j) add(i,j+n,1);            }        int ans=0;while(bfs())         ans+=dinic(0,inf);        if(ans==tot) puts("^_^");        else puts("T_T");       }    return 0;}
阅读全文
0 0
原创粉丝点击