bzoj 1116 并查集

15 篇文章 0 订阅

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





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值