bzoj 3624 贪心+Kruscal(并查集)

来源:互联网 发布:淘宝信用贷款突然没了 编辑:程序博客网 时间:2024/06/05 16:13

题意:n个点,m条无向边。共有两类边,分别是0类边和1类边,要求找出一棵最小生成树满足其中0类边恰好有K条,如果无解输出“no solution”

实际上就是一道经典的特殊的MST

跑两边Kruscal

第一遍:优先选择1类边,即在保证是树的前提下,能用1类边就用1类边,然后剩下的用0类边补全,则这些0类边是必须要选的,如果必选的0类边的数量大于K,则无解

第二遍:先加入上一次必须要选的0类边,然后在保证是树的前提下,在剩下的0类边里选取来补足K条,如果最后选择的0类边总数依旧小于K条,则无解,否则用1类边来补全最小生成树

type        rec=record            x,y,c:longint;end;var        n,m,k,tt,tx,ty,t1:longint;        i                :longint;        father           :array[0..20010] of longint;        l                :array[0..100010] of rec;        flag             :array[0..100010] of boolean;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,k);   for i:=1 to n do father[i]:=i;   for i:=1 to m do read(l[i].x,l[i].y,l[i].c);   tt:=0;   // use 1 as possible as you can   for i:=1 to m do     if l[i].c=1 then     begin        tx:=get_father(l[i].x);        ty:=get_Father(l[i].y);        if tx<>ty then        begin           father[tx]:=ty; inc(tt);           if tt=n-1 then break;        end;     end;   //find then necessary 0   for i:=1 to m do     if (l[i].c=0) and (tt<n-1) then     begin        tx:=get_father(l[i].x);        ty:=get_father(l[i].y);        if tx<>ty then        begin           inc(t1); inc(tt); father[tx]:=ty; flag[i]:=true;           if tt=n-1 then break;        end;     end;   //you have to use t1 0   if t1>k then   begin      writeln('no solution');exit;   end;   for i:=1 to n do father[i]:=i; tt:=0;   //use the necessary 0   for i:=1 to m do     if flag[i] then     begin        tx:=get_father(l[i].x);        ty:=get_father(l[i].y);        if tx<>ty then        begin           dec(k); inc(tt);           father[tx]:=ty;           if tt=n-1 then break;        end;     end;   //ensure use k 0   for i:=1 to m do     if (l[i].c=0) and not flag[i] and (tt<n-1) then     begin        tx:=get_father(l[i].x);        ty:=get_father(l[i].y);        if tx<>ty then        begin           dec(k); inc(tt);           father[tx]:=ty;           flag[i]:=true;           if (k=0) or (tt=n-1) then break;        end;     end;   //the number of 0 is less than k   if k>0 then   begin      writeln('no solution');exit;   end;   //find other 1 to make it complete   for i:=1 to m do     if (l[i].c=1) and (tt<n-1) then     begin        tx:=get_father(l[i].x);        ty:=get_father(l[i].y);        if tx<>ty then        begin           inc(tt);           father[tx]:=ty;           flag[i]:=true;           if tt=n-1 then break;        end;     end;   //   for i:=1 to m do if flag[i] then writeln(l[i].x,' ',l[i].y,' ',l[i].c);end.
——by Eirlys



0 0
原创粉丝点击