I and OI
Past...

题意:判断最小生成树是否唯一.

分析:先求出一棵最小生成树,记下最小权值为W0.然后枚举树上的每条边,去掉以后再求一次最小生成树,

只要出现权值等于W0,那么最小生成树一定不唯一.

因为范围小,所以这样的算法可以过.还有更优的算法.

code:

type  node=record
      u,v,w:longint;
      bo:boolean;
end;
const oo=100000000;
var   e:array[0..11000] of node;
      mst,f:array[0..110] of longint;
      min,d,datanum,n,m,o,now:longint;
      bool:boolean;


      procedure sort(l,r:longint);
      var   i,j,mid:longint;
            temp:node;
      begin
            i:=l; j:=r;
            mid:=e[(l+r)>>1].w;
            repeat
                   while e[i].w<mid do inc(i);
                   while e[j].w>mid do dec(j);
                   if i<=j then
                   begin
                         temp:=e[i];
                         e[i]:=e[j];
                         e[j]:=temp;
                         inc(i); dec(j);
                   end;
            until i>j;
            if i<r then sort(i,r);
            if j>l then sort(l,j);
      end;

      function getf(x:longint):longint;
      begin
            if f[x]<>x then f[x]:=getf(f[x]);
            exit(f[x]);
      end;

      procedure union(u,v:longint);
      begin   f[u]:=v;   end;

      function kruskal(v0:longint):longint;
      var   i,mst_count,mstweight:longint;
      begin
            e[v0].bo:=true;
            for i:=1 to n do f[i]:=i;
            mst_count:=0;
            mstweight:=0;
            for i:=1 to m do
            begin
                  if mst_count=n-1 then break;
                  if (not e[i].bo)and(getf(e[i].u)<>getf(e[i].v)) then
                  begin
                        inc(mst_count);
                        inc(mstweight,e[i].w);
                        if v0=0 then mst[mst_count]:=i;
                        union(getf(e[i].u),getf(e[i].v));
                  end;
            end;
            e[v0].bo:=false;
            if mst_count<n-1 then exit(-1)
            else exit(mstweight);
      end;


begin
      readln(datanum);
      for d:=1 to datanum do
      begin
            readln(n,m);
            if m=0 then
            begin writeln(0); continue; end;
            for o:=1 to m do readln(e[o].u,e[o].v,e[o].w);
            min:=kruskal(0);
            for o:=1 to n-1 do
            begin
                  now:=kruskal(mst[o]);
                  if now=min then
                  begin writeln('Not Unique!'); break; end;
            end;
            if now=min then continue
            else writeln(min);
      end;
end.

posted on 2011-08-10 16:00  exponent  阅读(861)  评论(0编辑  收藏  举报