题目描述
假面舞会 【问题描述】 一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会。 今年的面具都是主办方特别定制的。 每个参加舞会的人都可以在入场时选择 一个自己喜欢的面具。每个面具都有一个编号,主办方会把此编号告诉拿该面具 的人。 为了使舞会更有神秘感, 主办方把面具分为 k (k≥3)类, 并使用特殊的技术将 每个面具的编号标在了面具上,只有戴第 i 类面具的人才能看到戴第 i+1 类面具 的人的编号,戴第 k 类面具的人能看到戴第 1 类面具的人的编号。 参加舞会的人并不知道有多少类面具,但是栋栋对此却特别好奇,他想自己 算出有多少类面具,于是他开始在人群中收集信息。 栋栋收集的信息都是戴第几号面具的人看到了第几号面具的编号。如戴第 2 号面具的人看到了第 5 号面具的编号。栋栋自己也会看到一些编号,他也会根据 自己的面具编号把信息补充进去。 由于并不是每个人都能记住自己所看到的全部编号,因此,栋栋收集的信息 不能保证其完整性。现在请你计算,按照栋栋目前得到的信息,至多和至少有多 少类面具。由于主办方已经声明了 k≥3,所以你必须将这条信息也考虑进去。 【输入格式】 输入文件 party.in 第一行包含两个整数 n, m,用一个空格分隔,n 表示主办 方总共准备了多少个面具,m 表示栋栋收集了多少条信息。 接下来 m 行,每行为两个用空格分开的整数 a, b,表示戴第 a 号面具的人看 到了第 b 号面具的编号。相同的数对 a, b 在输入文件中可能出现多次。 【输出格式】 输出文件 party.out 包含两个数,第一个数为最大可能的面具类数,第二个数 为最小可能的面具类数。如果无法将所有的面具分为至少 3 类,使得这些信息都 满足,则认为栋栋收集的信息有错误,输出两个-1。 【输入样例一】 65 12 23 34 41 35 【输出样例一】 44 【输入样例二】 33 12 21 23 【输出样例二】 -1 -1 【数据规模和约定】 50%的数据,满足 n ≤ 300, m ≤ 1000; 100%的数据,满足 n ≤ 100000, m ≤ 1000000。
假面舞会
1 (* 2 *Problem: 假面舞会 3 *Author : Chen Yang 4 *Time : 2012.5.18 5 *State : Solved 6 *Memo : 图论、有向图找环 7 *) 8 program party; 9 const maxn=101000; 10 type 11 ty1=^ty2; 12 ty2=record 13 x,d:longint; 14 get:boolean; 15 next,up:ty1; 16 end; 17 18 var 19 n,m,i,a,b,min,max,cnt,tot:longint; 20 first:array[0..maxn] of ty1; 21 get:array[0..maxn] of boolean; 22 link,c,bel,cmin,cmax:array[0..maxn] of longint; 23 //================== 24 procedure insert(x,y,z:longint); 25 var 26 p,q:ty1; 27 begin 28 new(p); 29 p^.x:=y; p^.d:=z; p^.get:=false; 30 p^.next:=first[x]; first[x]:=p; 31 new(q); 32 q^.x:=x; q^.d:=-z; q^.get:=false; 33 q^.next:=first[y]; first[y]:=q; 34 q^.up:=p; p^.up:=q; 35 end; 36 //================== 37 procedure find(x,i:longint); 38 var 39 p:ty1; 40 begin 41 get[x]:=true; link[x]:=i; 42 bel[x]:=tot; 43 p:=first[x]; 44 while p<>nil do 45 begin 46 if not p^.get then 47 begin 48 p^.get:=true; p^.up^.get:=true; 49 if not get[p^.x] then find(p^.x,i+p^.d) else 50 if link[p^.x]-i-p^.d<>0 then 51 begin 52 inc(cnt); c[cnt]:=abs(link[p^.x]-i-p^.d); 53 end; 54 end; 55 p:=p^.next; 56 end; 57 end; 58 //================== 59 function gcd(x,y:longint):longint; 60 begin if y=0 then exit(x) else exit(gcd(y,x mod y)); end; 61 //================== 62 procedure main1; 63 var 64 i:longint; 65 begin 66 max:=c[1]; 67 for i:=2 to cnt do max:=gcd(max,c[i]); 68 for min:=3 to max do 69 begin 70 for i:=1 to cnt+1 do 71 if c[i] mod min<>0 then break; 72 if i=cnt+1 then break; 73 end; 74 if max<3 then 75 begin 76 min:=-1; max:=-1; 77 end; 78 end; 79 //================== 80 procedure main2; 81 var 82 i:longint; 83 begin 84 fillchar(cmin,sizeof(cmin),$7); 85 fillchar(cmax,sizeof(cmax),200); 86 for i:=1 to n do 87 begin 88 if cmin[bel[i]]>link[i] then cmin[bel[i]]:=link[i]; 89 if cmax[bel[i]]<link[i] then cmax[bel[i]]:=link[i]; 90 end; 91 for i:=1 to tot do inc(max,cmax[i]-cmin[i]+1); 92 if max>2 then min:=3 else 93 begin 94 min:=-1; max:=-1; 95 end; 96 end; 97 //================== 98 begin 99 assign(input,'party.in'); reset(input); 100 assign(output,'party.out'); rewrite(output); 101 read(n,m); 102 for i:=1 to m do 103 begin 104 read(a,b); insert(a,b,1); 105 end; 106 for i:=1 to n do 107 if not get[i] then 108 begin inc(tot); find(i,1); end; 109 if cnt>0 then main1 else main2; 110 writeln(max,' ',min); 111 close(input); close(output); 112 end.