下面是tyvj1111舞会的两种算法(pascal)、求大牛解释。

[复制链接]
查看11 | 回复3 | 2011-8-24 09:03:12 | 显示全部楼层 |阅读模式
FromAdmin☆舞会描述DescriptionVictoria是一位颇有成就的艺术家,他因油画作品《我爱北京天安门》闻名于世界。现在,他为了报答帮助他的同行们,准备开一个舞会。Victoria准备邀请n个已经确定的人,可是问题来了:这n个人每一个人都有一个小花名册,名册里面写着他所愿意交流的人的名字。比如说在A的人名单里写了B,那么表示A愿意与B交流;但是B的名单里不见的有A,也就是说B不见的想与A交流。但是如果A愿意与B交流,B愿意与C交流,那么A一定愿意与C交流。也就是说交流有传递性。Victoria觉得需要将这n个人分为m组,要求每一组的任何一人都愿意与组内其他人交流。并求出一种方案以确定m的最小值是多少。注意:自己的名单里面不会有自己的名字。输入格式InputFormat第一行一个数n。接下来n行,每i1行表示编号为i的人的小花名册名单,名单以0结束。1=n=200。输出格式OutputFormat一个数,m。样例输入SampleInput[复制数据]18018000110000005000000020样例输出SampleOutput[复制数据]16时间限制TimeLimitation各个测试点1s我算了传递闭包。programProject1;vari,n,j,k:byte;a:array[1..200,1..200]ofboolean;v:array[1..200]ofboolean;ans:longint;beginreadln(n);fori:=1tondobeginread(j);whilej0dobegina[i,j]:=true;read(j);end;end;fork:=1tondofori:=1tondoforj:=1tondoa[i,j]:=(a[i,j])or(a[i,k])and(a[k,j]);fori:=1tondov:=true;ans:=0;fori:=1tondoif(v)thenbeginv:=false;inc(ans);forj:=1tondoif(v[j])and(a[i,j])and(a[j,i])thenv[j]:=false;end;write(ans);end.听说有人用并查集而且过了,顿时傻了……代码如下varf:array[1..200]ofinteger;functionfind(x:longint):longint;beginiff[x]xthenf[x]:=find(f[x]);find:=f[x];end;proceduremain;varn,i,t,ans:longint;beginreadln(n);fori:=1tondof:=i;ans:=n;fori:=1tondobeginread(t);whilet0dobeginiffind(i)find(t)thenbegindec(ans);f[find(i)]:=find(t);end;read(t);end;end;writeln(ans);readln;readln;end;beginmain;end.为什么可以用并查集?3303010答案应该是2而并查集做得结果是1
回复

使用道具 举报

千问 | 2011-8-24 09:03:12 | 显示全部楼层
既然你都已经举出反例了,你还认为并查集是对的?你的问题是什么?追问有人用并查集做AC了--。
回复

使用道具 举报

千问 | 2011-8-24 09:03:12 | 显示全部楼层
想到一个比较烂的也是n^2的,仍旧用bool数组记录管理,f[i,j]=true,表示i接受j,依次读入关系若读入关系为a接受b,那么f[fa[a],fa]=true如果f[fa,fa[j]]defds123defds123f[fa[j],fa]=true就把两者合成一个并查集,并且在每次合并的时候,把其中一个人和其他所有人的关系赋给另一个。这样每个人会被加入并查集一次,所以每次插入复杂度n,扫一遍n,一共n^2。最后看有多少的并查集
回复

使用道具 举报

千问 | 2011-8-24 09:03:12 | 显示全部楼层
num为全局变量,在procedurework结尾要还原(-1),不单单是在主程序还原(清零)再不行看看是不是高度相等也能滑超时的问题加个记忆化搜索或用BFS、
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行