问题抽象成图论,对于每一对欢迎关系(A,B),我们从A向B连一条有向边,得到的图是有可能存在环的,
在原图上使用Tarjan算法,得到一个新图(有向无环),如果缩后仅剩一个点,答案为n,即任意点都被其他点欢迎,
否则统计每一个新点的出度,对于出度为0的点的个数
1:答案是该点包含的原图点数,其他的牛都不能被他们欢迎
>=2:答案为0,出度为0的点间互不欢迎。
View Code
1 program pku2186(input,output); 2 type 3 node=^link; 4 link=record 5 goal:longint; 6 next:node; 7 end; 8 var 9 l :array[0..11000] of node; 10 color :array[0..11000] of longint; 11 out :array[0..11000] of longint; 12 n,m :longint; 13 dfn,low :array[0..11000] of longint; 14 stack :array[0..20000] of longint; 15 instack :array[0..11000] of boolean; 16 colour,cnt,top:longint; 17 answer,answer_color,sum:longint; 18 procedure add(xx,yy:longint); 19 var 20 tt:node; 21 begin 22 new(tt); 23 tt^.goal:=yy; 24 tt^.next:=l[xx]; 25 l[xx]:=tt; 26 end;{ add } 27 procedure init; 28 var 29 i,xx,yy:longint; 30 begin 31 readln(n,m); 32 for i:=1 to n do 33 begin 34 instack[i]:=false; 35 dfn[i]:=0; 36 low[i]:=0; 37 color[i]:=0; 38 out[i]:=0; 39 l[i]:=nil; 40 end; 41 for i:=1 to m do 42 begin 43 readln(xx,yy); 44 add(xx,yy); 45 end; 46 end;{ init } 47 procedure dfs(now:longint); 48 var 49 t:node; 50 begin 51 inc(cnt); 52 dfn[now]:=cnt; 53 low[now]:=cnt; 54 inc(top); 55 stack[top]:=now; 56 instack[now]:=true; 57 t:=l[now]; 58 while t<>nil do 59 begin 60 if dfn[t^.goal]=0 then 61 begin 62 dfs(t^.goal); 63 if low[t^.goal]<low[now] then 64 low[now]:=low[t^.goal]; 65 end 66 else 67 begin 68 if (instack[t^.goal])and(dfn[t^.goal]<low[now]) then 69 low[now]:=dfn[t^.goal]; 70 end; 71 t:=t^.next; 72 end; 73 if dfn[now]=low[now] then 74 begin 75 inc(colour); 76 while true do 77 begin 78 color[stack[top]]:=colour; 79 instack[stack[top]]:=false; 80 dec(top); 81 if stack[top+1]=now then 82 break; 83 end; 84 end; 85 end;{ dfs } 86 procedure tarjan(); 87 var 88 i:longint; 89 begin 90 colour:=0; 91 for i:=1 to n do 92 if dfn[i]=0 then 93 dfs(i); 94 end;{ tarjan } 95 procedure main; 96 var 97 t:node; 98 i:longint; 99 begin 100 for i:=1 to n do 101 begin 102 t:=l[i]; 103 while t<>nil do 104 begin 105 if color[i]<>color[t^.goal] then 106 inc(out[color[i]]); 107 t:=t^.next; 108 end; 109 end; 110 answer_color:=0; 111 sum:=0; 112 answer:=0; 113 for i:=1 to colour do 114 if out[i]=0 then 115 begin 116 inc(sum); 117 answer_color:=i; 118 end; 119 if colour=1 then 120 begin 121 answer:=n; 122 exit; 123 end; 124 if sum>=2 then 125 answer:=0; 126 if sum=1 then 127 begin 128 for i:=1 to n do 129 if color[i]=answer_color then 130 inc(answer); 131 end; 132 end;{ main } 133 procedure print; 134 begin 135 writeln(answer); 136 end;{ print } 137 begin 138 init; 139 tarjan; 140 main; 141 print; 142 end.