输出要用puts!!!!!
输出要用puts!!!!!
输出要用puts!!!!!
重要的事情说三遍。。
分析:比较简单的网络流了,人向源连边,床向汇点连边,人向能睡的床连边,跑最大流,看看能不能全部睡咯。
事实上,其实这也是网络流的经典套路,基本上能把题目化成两堆点,一堆向源连边,一堆向汇连边,然后两堆点之间互相连边。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define T 101
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=3e5+5;
const int M=2e3+5;
const int inf=1e9;
int n,m;
bool bz[N];
int dis[M],head[N],go[N],next[N],val[N],q[N],cnt=1,ans,tot;
inline bool bfs()
{
int t=0,w=1;
memset(dis,-1,sizeof(dis));
dis[0]=0;
q[1]=0;
while (t<w)
{
int x=q[++t];
for(int i=head[x];i;i=next[i])
{
int v=go[i];
if (val[i]&&dis[v]==-1)
{
dis[v]=dis[x]+1;
q[++w]=v;
}
}
}
return dis[T]!=-1;
}
inline int dfs(int x,int f)
{
if (x==T)return f;
int w,used=0;
for(int i=head[x];i;i=next[i])
{
int v=go[i];
if (val[i]&&dis[v]==dis[x]+1)
{
w=f-used;
w=dfs(v,min(w,val[i]));
val[i]-=w;
val[i^1]+=w;
used+=w;
if (used==f)return f;
}
}
if (!used)dis[x]=-1;
return used;
}
inline void add(int x,int y,int z)
{
go[++cnt]=y;
val[cnt]=z;
next[cnt]=head[x];
head[x]=cnt;
}
inline void ins(int x,int y,int z)
{
add(x,y,z);
add(y,x,0);
}
inline void dinic()
{
while (bfs())ans+=dfs(0,inf);
}
int main()
{
int cas;
scanf("%d",&cas);
while (cas--)
{
scanf("%d",&n);
memset(head,0,sizeof(head));
cnt=1;
tot=0;
ans=0;
fo(i,1,n)
{
scanf("%d",&bz[i]);
if (bz[i])ins(i+n,T,1);
}
fo(i,1,n)
{
int x;
scanf("%d",&x);
if ((bz[i]&&!x)||!bz[i])
{
ins(0,i,1);
tot++;
}
}
fo(i,1,n)
fo(j,1,n)
{
int x;
scanf("%d",&x);
if (x||i==j)ins(i,j+n,1);
}
dinic();
if (ans==tot)puts("^_^");
else puts("T_T");
}
return 0;
}