Description
Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 你要把其中一些road变成单向边使得:每个town都有且只有一个入度
Input
第一行输入n m.1 <= n<= 100000,1 <= m <= 200000 下面M行用于描述M条边.
Output
TAK或者NIE 常做POI的同学,应该知道这两个单词的了...
第一眼不冷静的想写个dfs,结果写着写着发现了一个显然的性质:
由于它要求n个点每个点的入度都为1,那么在一个联通块里,如果不存在环那么一定是不可以的(因为有个点是回不去的)
那么还写什么sb的dfs,直接并查集维护连通块、对于每个并查集的根维护一个是否有环的标记就行了
对于当前新边,如果两个端点已经在一个联通块里,那么显然会形成环,标记置为true,否则合并
合并的时候,任意一个的标记为真则合并后的标记为真
最后每个连通块扫一遍就可以了
在这道题,并查集维护的是连通块的信息,更近一步,维护的是判环
var
n,m,x,y,tx,ty :longint;
father :array[0..100010] of longint;
flag :array[0..100010] of boolean;
i :longint;
function get_father(x:longint):longint;
begin
if x=father[x] then exit(x);
father[x]:=get_father(father[x]);
exit(father[x]);
end;
begin
read(n,m);
for i:=1 to n do father[i]:=i;
for i:=1 to m do
begin
read(x,y);
tx:=get_father(x);
ty:=get_father(y);
if tx<>ty then
begin
father[tx]:=ty;
if flag[tx] or flag[ty] then flag[ty]:=true;
end else flag[ty]:=true;
end;
for i:=1 to n do if not flag[get_father(i)] then
begin
writeln('NIE');exit;
end;
writeln('TAK');
end.
——by Eirlys