现在的位置: 首页 > 综合 > 正文

poj1639

2018年01月15日 ⁄ 综合 ⁄ 共 3483字 ⁄ 字号 评论关闭

【题意】

k度生成树。

【输入】

第一行:n条边

接下来n行描述边

Park为限度点

【输出】

”Total miles driven: “+最小生成树权值

比较麻烦的一道题

写了4,336 字节

组织的可能不是太好

单纯的讲一下做法

证明黑书上有

1、把跟限度点之间边去掉后生成最小生成树,得到一片森林

2、对于森林里的每棵树,选其中跟限度点有边且该边权值最小的连上

如果有n棵树,则现在则为n度最小生成树

3、接下来就是利用增加度来尝试减少费用了

尝试每条与限度点相连的边,连上该条边理所应当的需要剪短一条从该点到限度点路径上的边

当然是减最大的。

所以每次剪之前,可以做一遍dfs来确定每个点到限度点路径上权值最大的边

总体复杂度O(kn)

就是这样,感觉说的非常不清,不愧是语文期末94的人啊。

program poj1639;
type
  node=record
         x,y,c:longint;
       end;
var
  n,i,j,k,t,tot,x,y,c,no,all,ans,now,minn,u,v,maxn:longint;
  order,a,b:string;
  line:array [0..10001] of node;
  temp:node;
  trie:array [0..10001,'a'..'z'] of longint;
  max,incr,father,who:array [-1..10001] of longint;
  nn,last,roo,next,point,cost:array [-1..10001] of longint;
  yes:array [-1..10001] of boolean;

procedure swap (var a,b:longint);
var
  i:longint;
begin
  i:=a;
  a:=b;
  b:=i;
end;

function find (st:string):longint;
var
  i,k:longint;
begin
  i:=0;
  for k:=1 to length(st) do
    begin
      if trie[i][st[k]]=0 then
        begin
          inc(tot);
          trie[i][st[k]]:=tot;
        end;
      i:=trie[i][st[k]];
    end;
  if who[i]=0 then
    begin
      inc(no);
      who[i]:=no;
    end;
  exit(who[i]);
end;

procedure qsort (s,e:longint);
var
  i,j,k:longint;
begin
  if s>=e then exit;
  i:=s;
  j:=e;
  k:=line[(s+e) div 2].c;
  while i<=j do
    begin
      while (i<=j)and(line[i].c<k) do inc(i);
      while (i<=j)and(line[j].c>k) do dec(j);
      if i>j then break;
      temp:=line[i];
      line[i]:=line[j];
      line[j]:=temp;
      inc(i);
      dec(j);
    end;
  qsort(s,j);
  qsort(i,e);
end;

function root (now:longint):longint;
begin
  if father[now]=0 then exit(now);
  father[now]:=root(father[now]);
  exit(father[now]);
end;

procedure connect (s,e,c,ll:longint);
begin
  inc(all);
  point[all]:=e;
  cost[all]:=c;
  next[all]:=roo[s];
  last[roo[s]]:=all;
  roo[s]:=all;
  nn[all]:=ll;
end;

procedure deletee (now,wh:longint);
begin
  if next[now]<>0 then last[next[now]]:=last[now];
  if last[now]<>0 then next[last[now]]:=next[now];
  if roo[wh]=now then roo[wh]:=next[now];
end;

procedure dfs (now,maxn:longint);
var
  i:longint;
begin
  yes[now]:=true;
  i:=roo[now];
  max[now]:=maxn;
  while i<>0 do
    begin
      if not yes[point[i]] then
        if cost[i]>cost[maxn] then dfs(point[i],i)
                              else dfs(point[i],maxn);
      i:=next[i];
    end;
end;

begin
  readln(n);
  trie[0,'p']:=1;
  trie[1,'a']:=2;
  trie[2,'r']:=3;
  trie[3,'k']:=4;
  tot:=4;
  no:=0;
  who[4]:=-1;
  for i:=1 to n do
    begin
      readln(order);
      a:=copy(order,1,pos(' ',order)-1);
      delete(order,1,pos(' ',order));
      b:=copy(order,1,pos(' ',order)-1);
      delete(order,1,pos(' ',order));
      val(order,line[i].c,c);
      for j:=1 to length(a) do
        if a[j]<='Z' then a[j]:=chr(ord(a[j])+32);
      for j:=1 to length(b) do
        if b[j]<='Z' then b[j]:=chr(ord(b[j])+32);
      line[i].x:=find(a);
      line[i].y:=find(b);
      if line[i].x>line[i].y then swap(line[i].x,line[i].y);
    end;
  read(t);
  qsort(1,n);
  all:=0;
  now:=0;
  for i:=1 to n do
    if (line[i].x<>-1)and(line[i].y<>-1)and(root(line[i].x)<>root(line[i].y)) then
      begin
        father[root(line[i].x)]:=root(line[i].y);
        now:=now+line[i].c;
        connect(line[i].x,line[i].y,line[i].c,all+2);
        connect(line[i].y,line[i].x,line[i].c,all);
      end;
  fillchar(incr,sizeof(incr),0);
  fillchar(yes,sizeof(yes),false);
  k:=0;
  for i:=1 to n do
    if ((line[i].x=-1)or(line[i].y=-1))and(not yes[root(line[i].x+line[i].y+1)]) then
      begin
        inc(k);
        yes[root(line[i].x+line[i].y+1)]:=true;
        incr[root(line[i].x+line[i].y+1)]:=line[i].c;
        now:=now+line[i].c;
        connect(line[i].x,line[i].y,line[i].c,all+2);
        connect(line[i].y,line[i].x,line[i].c,all);
      end;
  line[0].c:=-maxlongint;
  ans:=now;
  for i:=k+1 to t do
    begin
      fillchar(yes,sizeof(yes),false);
      maxn:=0;
      dfs(-1,0);
      for j:=1 to n do
        if (line[j].x=-1)and(cost[max[line[j].y]]-line[j].c>maxn) then
          begin
            maxn:=cost[max[line[j].y]]-line[j].c;
            u:=line[j].y;
            v:=j;
          end;
      if maxn=0 then break;
      now:=now-maxn;
      if now<ans then ans:=now;
      deletee(max[u],point[nn[max[u]]]);
      deletee(nn[max[u]],u);
      connect(line[v].x,line[v].y,line[v].c,all+2);
      connect(line[v].y,line[v].x,line[v].c,all);
    end;
  writeln('Total miles driven: ',ans);
end.
【上篇】
【下篇】

抱歉!评论已关闭.