正解:最大流
解题报告:
这种一看就很网络流鸭,直接说咋建图趴.
考虑把在校的人拆成人和床.$S$连向所有不回家的人,所有床连向$T$,认识的人之间人向床连边,跑个最大流就成.
$over$
记得每个人要向自己的床连边,,,不然就可以获得$10pts$的好成绩(居然还有$10pts$,,,,$/jk$
#include<bits/stdc++.h>
using namespace std;
#define t(i) edge[i].to
#define w(i) edge[i].wei
#define rp(i,x,y) for(int i=x;i<=y;++i)
#define e(i,x) for(int i=head[x];~i;i=edge[i].nxt)
#define E(i,x) for(int &i=cur[x];~i;i=edge[i].nxt) const int N=+,inf=1e9;
int n,m,S,T,head[N],cur[N],ed_cnt=-,dep[N];
int gd[N],gs[N];
struct ed{int to,nxt,wei;}edge[N<<];
queue<int>Q; void ad(int x,int y,int z){edge[++ed_cnt]=(ed){x,head[y],z};head[y]=ed_cnt;edge[++ed_cnt]=(ed){y,head[x],};head[x]=ed_cnt;}
bool bfs()
{
memset(dep,,sizeof(dep));dep[S]=;Q.push(S);
while(!Q.empty()){int nw=Q.front();Q.pop();e(i,nw)if(w(i) && !dep[t(i)])dep[t(i)]=dep[nw]+,Q.push(t(i));}return dep[T];
}
int dfs(int nw,int fl)
{
if(!(nw^T) || !fl)return fl;;int ret=;
E(i,nw)if(dep[t(i)]==dep[nw]+){int d=dfs(t(i),min(fl,w(i)));w(i)-=d,w(i^)+=d,fl-=d,ret+=d;if(!fl)return ret;}
return ret;
}
int dinic(){int ret=;while(bfs()){rp(i,S,T)cur[i]=head[i];while(int d=dfs(S,inf))ret+=d;}return ret;} int main()
{
int t;scanf("%d",&t);
while(t--)
{
scanf("%d",&n);S=,T=n<<|;memset(head,-,sizeof(head));ed_cnt=-;int cnt=;
rp(i,,n){scanf("%d",&gd[i]);if(gd[i])ad(T,i+n,);else ad(i,S,),++cnt;}rp(i,,n){scanf("%d",&gs[i]);if(gd[i] && !gs[i])ad(i,S,),++cnt;}
rp(i,,n)rp(j,,n){int x;scanf("%d",&x);if(x)ad(j+n,i,),ad(i+n,j,);if(i==j)ad(i+n,i,);}
printf(dinic()==cnt?"^_^\n":"T_T\n");
}
return ;
}