货车运输(codevs 3287)题解

【问题描述】

    A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

【样例输入】

    4 3 
    1 2 4 
    2 3 3 
    3 1 1 
    3
    1 3 
    1 4 
    1 3

【样例输出】

    3
    -1
    3

【解题思路】

    本题为NOIP2013提高组day1第三题,首先我们可以看出这是一道求最大生成树的问题,用kruscal求出,对于我们要找的两个点,先判断是否有边相连,没有直接输出-1,然后将选中的边建成一棵带权树,接着我们求LCA来求两点之间的最小载重量,这里可以去看看LCA,我用的是倍增的方法,然后边求LCA边算两点到该点的最小值,最后输出即可。

【代码实现】

 1 uses math;
  2 const mi:array[0..14]of longint=(1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384);
  3 var n,m,q,tot,i,j,x,y:longint;
  4     a,b,v:array[0..50000]of longint;
  5     fa,h:array[0..10000]of longint;
  6     flag:array[0..10000]of boolean;
  7     first,last,next,w:array[0..100000]of longint;
  8     f,g:array[0..10000,0..14]of longint;
  9 function gf(x:longint):longint;
 10 begin
 11  if fa[x]=x then
 12   exit(x);
 13  fa[x]:=gf(fa[x]);
 14  exit(fa[x]);
 15 end;
 16 procedure swap(var x,y:longint);
 17 var t:longint;
 18 begin
 19  t:=x;
 20  x:=y;
 21  y:=t;
 22 end;
 23 procedure sort(l,r: longint);
 24       var
 25          i,j,x,y: longint;
 26       begin
 27          i:=l;
 28          j:=r;
 29          x:=v[(l+r) div 2];
 30          repeat
 31            while v[i]>x do
 32             inc(i);
 33            while x>v[j] do
 34             dec(j);
 35            if not(i>j) then
 36              begin
 37                 swap(a[i],a[j]);
 38                 swap(b[i],b[j]);
 39                 swap(v[i],v[j]);
 40                 inc(i);
 41                 j:=j-1;
 42              end;
 43          until i>j;
 44          if l<j then
 45            sort(l,j);
 46          if i<r then
 47            sort(i,r);
 48       end;
 49 procedure insert(x,y,v:longint);
 50 begin
 51  inc(tot);
 52  w[tot]:=v;
 53  last[tot]:=y;
 54  next[tot]:=first[x];
 55  first[x]:=tot;
 56 end;
 57 procedure dfs(x,dep:longint);
 58 var i:longint;
 59 begin
 60  flag[x]:=true;
 61  h[x]:=dep;
 62  i:=first[x];
 63  while i<>0 do
 64   begin
 65    if not flag[last[i]] then
 66     begin
 67      f[last[i],0]:=x;
 68      g[last[i],0]:=w[i];
 69      dfs(last[i],dep+1);
 70     end;
 71    i:=next[i];
 72   end;
 73 end;
 74 function ans(x,y:longint):longint;
 75 var k:longint;
 76 begin
 77  ans:=maxlongint;
 78  if h[x]<h[y] then
 79   swap(x,y);
 80  while h[x]>h[y] do
 81   begin
 82    k:=0;
 83    while h[x]-h[y]>=mi[k+1] do
 84     inc(k);
 85    ans:=min(ans,g[x,k]);
 86    x:=f[x,k];
 87   end;
 88  while x<>y do
 89   begin
 90    if f[x,0]=f[y,0] then
 91     begin
 92      ans:=min(ans,min(g[x,0],g[y,0]));
 93      break;
 94     end;
 95    k:=0;
 96    while (f[x,k+1]<>f[y,k+1])and(h[x]>=mi[k+1]) do
 97     inc(k);
 98    ans:=min(ans,min(g[x,k],g[y,k]));
 99    x:=f[x,k];
100    y:=f[y,k];
101   end;
102 end;
103 begin
104  readln(n,m);
105  for i:=1 to m do
106   readln(a[i],b[i],v[i]);
107  sort(1,m);
108  for i:=1 to n do
109   fa[i]:=i;
110  for i:=1 to m do
111   if gf(a[i])<>gf(b[i]) then
112    begin
113     fa[fa[a[i]]]:=fa[b[i]];
114     insert(a[i],b[i],v[i]);
115     insert(b[i],a[i],v[i]);
116    end;
117  for i:=1 to n do
118   if not flag[i] then
119    dfs(1,0);
120  i:=1;
121  while mi[i]<n do
122   begin
123    for j:=1 to n do
124     if h[j]>=mi[i] then
125      begin
126       f[j,i]:=f[f[j,i-1],i-1];
127       g[j,i]:=min(g[j,i-1],g[f[j,i-1],i-1]);
128      end;
129    inc(i);
130   end;
131  readln(q);
132  for i:=1 to q do
133   begin
134    readln(x,y);
135    if gf(x)=gf(y) then
136     writeln(ans(x,y))
137    else
138     writeln(-1);
139   end;
140 end.

 

转载于:https://www.cnblogs.com/PengBoLiuXu/p/4550037.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值