5777. 【NOIP2008模拟】小x玩游戏
Description
今天,小x因为太无聊,就在玩游戏。这个游戏有两个队伍,然后他们在游戏里面打来打去。
但小x遇到了难题。他不知道自己的队友是谁。他只知道总共有两个队伍,每队有n个人和很多组击杀情况。他想问你,现在他能否知道两个队伍分别有谁。你可以帮助小x吗?由于小x是个游戏狂魔,所以他玩了很多局游戏。
但小x遇到了难题。他不知道自己的队友是谁。他只知道总共有两个队伍,每队有n个人和很多组击杀情况。他想问你,现在他能否知道两个队伍分别有谁。你可以帮助小x吗?由于小x是个游戏狂魔,所以他玩了很多局游戏。
Input
第一行有一个t,表示小y共玩了t局游戏。
接下来有t组数据,每组数据第一行有一个n,m,表示每队有n个人,有m组击杀情况,接下来m行每行两个字符串s1,s2,表示s1杀了s2,其中s1,s2的长度均不超过10(数据保证两个字符串都由小写字母组成)。注意一个人可以被击杀多次、一个人可以被曾经杀死过的人给杀死。
接下来有t组数据,每组数据第一行有一个n,m,表示每队有n个人,有m组击杀情况,接下来m行每行两个字符串s1,s2,表示s1杀了s2,其中s1,s2的长度均不超过10(数据保证两个字符串都由小写字母组成)。注意一个人可以被击杀多次、一个人可以被曾经杀死过的人给杀死。
Output
总共有t行,每行一个“YES”或“NO”,YES表示符合题目条件,NO表示不符合。
Solution
开双hash来记录字符串,然后连边。
然后判断是否合法。先找到一个点,做如下图的操作:
dfs中若有一个点连另一个点的标记相同,则错了,
假设点3可以到点7,则错了。
最后判断A和B的个数是否等于n即可。
代码
1 const 2 mo1=10000009; 3 mo2=10000007; 4 type 5 arr=record 6 y,next:longint; 7 end; 8 var 9 bo:boolean; 10 n,m,nm,mn,tt:longint; 11 e:array [0..200001] of arr; 12 a,b:array [1..11] of longint; 13 ls,v:array [0..4001] of longint; 14 ha1,ha2:array [0..mo1,1..2] of longint; 15 16 function hash1(x:longint):longint; 17 var 18 i:longint; 19 begin 20 i:=x; 21 while (ha1[i,1]<>0) and (ha1[i,1]<>x) do 22 i:=(i+1) mod mo1; 23 exit(i); 24 end; 25 26 function hash2(x:longint):longint; 27 var 28 i:longint; 29 begin 30 i:=x; 31 while (ha2[i,1]<>0) and (ha2[i,1]<>x) do 32 i:=(i+1) mod mo2; 33 exit(i); 34 end; 35 36 procedure add(x,y:longint); 37 begin 38 inc(mn); 39 e[mn].y:=y; e[mn].next:=ls[x]; 40 ls[x]:=mn; 41 end; 42 43 procedure init; 44 var 45 i,j,l,p,t1,t2,k1,k2,kk1,kk2,x,y:longint; 46 s:string; 47 begin 48 fillchar(ha1,sizeof(ha1),0); 49 fillchar(ls,sizeof(ls),0); 50 fillchar(e,sizeof(e),0); 51 readln(n,m); 52 nm:=0; mn:=0; 53 for i:=1 to m do 54 begin 55 readln(s); 56 l:=length(s); p:=pos(' ',s); 57 t1:=0; t2:=0; 58 for j:=p-1 downto 1 do 59 begin 60 t1:=(t1+(ord(s[j])-96)*a[p-j]) mod mo1; 61 t2:=(t2+(ord(s[j])-96)*b[p-j]) mod mo2; 62 end; 63 k1:=hash1(t1); kk1:=hash2(t2); 64 if ha1[k1,1]=0 then 65 begin 66 inc(nm); 67 ha1[k1,1]:=t1; ha1[k1,2]:=nm; 68 ha2[kk1,1]:=t2; ha2[kk1,2]:=nm; 69 end else 70 if ha2[kk1,1]=0 then 71 begin 72 inc(nm); 73 ha2[kk1,1]:=t2; ha2[kk1,2]:=nm; 74 end; 75 76 t1:=0; t2:=0; 77 for j:=l downto p+1 do 78 begin 79 t1:=(t1+(ord(s[j])-96)*a[l-j+1]) mod mo1; 80 t2:=(t2+(ord(s[j])-96)*b[l-j+1]) mod mo2; 81 end; 82 k2:=hash1(t1); kk2:=hash2(t2); 83 if ha1[k2,1]=0 then 84 begin 85 inc(nm); 86 ha1[k2,1]:=t1; ha1[k2,2]:=nm; 87 ha2[kk2,1]:=t2; ha2[kk2,2]:=nm; 88 end else 89 if ha2[kk2,1]=0 then 90 begin 91 inc(nm); 92 ha2[kk2,1]:=t2; ha2[kk2,2]:=nm; 93 end; 94 add(ha2[kk1,2],ha2[kk2,2]); 95 add(ha2[kk2,2],ha2[kk1,2]); 96 end; 97 end; 98 99 procedure dfs(x,w:longint); 100 var 101 i:longint; 102 begin 103 if not bo then exit; 104 i:=ls[x]; v[x]:=w; 105 if w=1 then w:=2 106 else w:=1; 107 while i<>0 do 108 begin 109 if v[e[i].y]=0 then dfs(e[i].y,w) else 110 if v[e[i].y]<>w then 111 begin 112 bo:=false; 113 exit; 114 end; 115 i:=e[i].next; 116 end; 117 end; 118 119 procedure print; 120 var 121 i,ans:longint; 122 begin 123 ans:=0; 124 for i:=1 to nm do 125 if v[i]=1 then inc(ans); 126 if (ans=n) and (nm-ans=n) and bo then writeln('YES') 127 else writeln('NO'); 128 end; 129 130 procedure try1; 131 var 132 i:longint; 133 begin 134 a[1]:=1; b[1]:=1; 135 for i:=2 to 10 do 136 begin 137 a[i]:=(a[i-1]*107) mod mo1; 138 b[i]:=(b[i-1]*97) mod mo2; 139 end; 140 end; 141 142 begin 143 assign(input,'game.in'); 144 assign(output,'game.out'); 145 reset(input); 146 rewrite(output); 147 try1; 148 readln(tt); 149 while tt>0 do 150 begin 151 init; 152 fillchar(v,sizeof(v),0); 153 bo:=true; 154 dfs(1,1); 155 print; 156 dec(tt); 157 end; 158 close(input); 159 close(output); 160 end.