解题报告 Dormitory
Dormitory
【题目描述】
小蛮妹子有许多的,什么棉花糖啦,蜥蜴啊,小乌龟啊,只有你想不到的没有她没有的。
小蛮妹子的小宠物都住在一个漂亮的大屋子里,每个人都有自己的床位,但是由于小蛮妹子的宠物太多了,以至于这些宠物之间并不是都互相认识。
这些宠物们也有自己的朋友,这些朋友一直羡慕他们住的漂亮大屋子,于是有一天,小蛮妹子出去玩了,一些小宠物也偷偷出去玩了,那些留守的小宠物们开始招待来访的客人。
这些来客都打算在这里住一晚上,可是安排床位就出了麻烦。每个小宠物都只愿意在自己的直接朋友或自己的床上(如果它是小蛮的宠物)睡觉,且一物睡一张床。
询问是否能有一个方案来满足所有在留宿的宠物都能住宿。
【输入格式】
第一行一个数 T 表示数据组数。
接下来 T 组数据。
每组数据第一行一个数 n 表示涉及到的总宠物数(包括小蛮的宠物和来客)。
接下来一行 n 个数,第 i 个数表示第 i 个个宠物是否是在小蛮的宠物 (0 表示不是,1 表示是)。再接下来一行 n 个数,第 i 个数表示第 i 个人是否出去玩(0 表示不出去,1 表示出去)注意如果第 i 个人不是小蛮的宠物,那么这个位置上的数是一个随机的数,你应该在读入以后忽略它)。
接下来 n 行,每行 n 个数,第 i 行第 j 个数表示 i 和 j 是否认识 (1 表示认识,0 表示不认识,第 i 行 i 个的值为 0,但是显然自己还是可以睡自己的床),认识的关系是
相互的。
【输出格式】
每一行对应每组数据
若存在方案满足条件 输出 ^.^ ,否则输出 T.T (只有三个字符,没有空格等其他内容)
【输入样例】
1
3
1 1 0
0 1 0
0 1 1
1 0 0
1 0 0
【输出样例】
^.^
【数据hint】
对于 30% 的数据满足 1 ≤ n ≤ 12。
对于 100% 的数据满足 1 ≤ n ≤ 50,1 ≤ T ≤ 20。
对于这种问题,本人已开始本来想用匈牙利来着,但是,猛然想起来,二分图不是 NOIP 考察范围。
后来极度后悔,因为出这个题的仁兄不会在乎 NOIP 考不考的......TAT
算法,毫无疑问,就是匈牙利。
将需要睡觉的动物(包括没出去玩的和来做客的)和相对应的可以让它用来睡觉的床(也就是所有是小蛮的宠物的动物的床)之间连一条边。
然后,跑一边匈牙利中的 find 函数。
如果所有的需要睡觉的动物都可以匹配上,那么显然可以成功,不然则不可以。
代码 (艾 FHAI)
var
a:array[0..55,0..55]of longint;
l,r:array[0..55]of longint;
pt,ah:array[0..55]of boolean;
v:array[0..55]of boolean;
res:array[0..55]of longint;
i,j,n,t,z,x,rr,ll,ans:longint;
function find(x:longint):boolean;
var j,tem:longint;
begin
//writeln('x,',x);
for j:=1 to rr do
if (not v[r[j]])and(a[x,r[j]]=1) then
begin
tem:=r[j];
v[tem]:=true;
if (res[tem]=0) or (find(res[tem])) then
begin
res[tem]:=x;
//writeln('tem,',tem,',',res[tem]);
exit(true);
end;
end;
exit(false);
end; //----------->话说,这个是可以背下来的。
begin
assign(input,'dormitory.in');reset(input);
assign(output,'dormitory.out');rewrite(output);
readln(t);
for z:=1 to t do
begin
fillchar(pt,sizeof(pt),false);
fillchar(ah,sizeof(ah),false);
ll:=0;rr:=0;ans:=0;
readln(n);
for i:=1to n do
begin
read(x);
if x=1 then
begin
inc(rr);r[rr]:=i;pt[i]:=true;
end
else
begin
inc(ll);l[ll]:=i;ah[i]:=true;
end;
end;
readln;
for i:=1to n do
begin
read(x);
if (pt[i]) and (x=0) then
begin
inc(ll);l[ll]:=i;ah[i]:=true;
end;
end;
readln;
//for i:=1to ll do write(l[i]);writeln;
//for j:=1 to rr do write(r[j]);writeln;
for i:=1 to n do
begin
for j:=1to n do
read(a[i,j]);
readln;
end;
for i:=1to n do a[i,i]:=1;
if ll>rr then
begin
writeln('T.T');
continue;
end;
{for i:=1 to ll do
for j:=1to rr do
if a[l[i],r[j]]=1 then write(l[i],',',r[j],',');writeln; }
fillchar(res,sizeof(res),0);
for i:=1 to ll do
begin
fillchar(v,sizeof(v),false);
if find(l[i]) then inc(ans);
end;
if ans>=ll then writeln('^.^')
else writeln('T.T');
//for i:=1to rr do write(r[i],',',res[r[i]],'/');writeln;
end;
close(input);close(output);
end.
本人马上发一篇有关匈牙利的博客,敬请关注。