タイトル説明
学校の休日は······何人かの学生は家に行きましたが、宿泊は問題があるので、そこの前に一部の学生は、良い友人を訪問します。
たとえば、AとBは、学校の生徒、家に帰るA、およびビューBのCあり、CとAは知りません。私たちは、一人一人だけ寝ると人間のベッドの独自の直接的な知識できることを前提としています。だから一つの解決策は、ベッドBにスリープ状態にBとCのベッドをスリープ状態にあります 現実は非常に複雑になる可能性があり、一部の人々は、多くの学生が必ずしも学生の間でお互いを知らない知っているかもしれません。
私たちが知っているN人の合計、と誰もが私たちの学生が各家庭かどうかを知って、私たちの学生ではないです知っています。生徒たちのすべてが家に帰ると住む場所を持っている彼らの他の人を見ないようにQ.プログラムがあります。
解決
見て、轟音ああ、二部グラフの最大マッチングを実行する必要はありませんでした。
もちろんベッドと照合すると、(徒歩含む)の学生のベッドを持っている(学生や部外者を含む)の人が歩いていなかった学校にとどまります。最大マッチングの場合はその後、我々は、左の部品ノード、ノードなど、すべてのベッドの右側の一部として、学校内のすべての人を置くことができます\(= \)学生の数は、学校で実行可能なプログラムをご利用いただけます。
ハンガリーや最大流量、私が書く最大流量は、あなたの手を練習します。
参照コード
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define N 51
#define M 10010
#define INF 0x3f3f3f3f
using namespace std;
inline int read()
{
int f=1,x=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
struct rec{
int next,ver,leng;
}g[M<<1];
int head[M],tot,d[M],n,num;
int is[N],home[N];
inline void add(int x,int y,int val)
{
g[++tot].ver=y,g[tot].leng=val;
g[tot].next=head[x],head[x]=tot;
}
inline bool bfs()
{
memset(d,0,sizeof(d));
queue<int> q;
d[0]=1;q.push(0);
while(q.size()){
int x=q.front();q.pop();
for(int i=head[x];i;i=g[i].next){
int y=g[i].ver,z=g[i].leng;
if(!z||d[y]) continue;
d[y]=d[x]+1;
q.push(y);
if(y==n*2+1) return 1;
}
}
return 0;
}
inline int dinic(int x,int flow)
{
if(x==n*2+1) return flow;
int rest=flow;
for(int i=head[x];i;i=g[i].next){
int y=g[i].ver,z=g[i].leng;
if(!z||d[y]!=d[x]+1) continue;
int k=dinic(y,min(rest,z));
if(!k) d[y]=0;
else{
g[i].leng-=k;
g[i^1].leng+=k;
rest-=k;
}
}
return flow-rest;
}
int main()
{
int T;
T=read();
while(T--){
memset(head,0,sizeof(head));
memset(is,0,sizeof(is));//在校学生为 1
memset(home,0,sizeof(home));//回家的人为 1
tot=1,num=0;
n=read();
for(int i=1;i<=n;++i){
is[i]=read();
if(is[i]) add(i+n,n*2+1,1),add(n*2+1,i+n,0);
}
for(int i=1;i<=n;++i){
home[i]=read();
if(!home[i]||!is[i]) add(0,i,1),add(i,0,0),num++;
}
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j){
int x=read();
if(j>i) continue;
if(i==j&&!home[i]) add(i,i+n,1),add(i+n,i,0);
else if(x) add(i,j+n,1),add(j+n,i,0),add(j,i+n,1),add(i+n,j,0);
}
int now,ans=0;
while(bfs())
while((now=dinic(0,INF))) ans+=now;
if(ans==num) printf("^_^\n");
else printf("T_T\n");
}
return 0;
}