[Vijos P1843] Noip2013Day1T3

4 篇文章 0 订阅
3 篇文章 0 订阅

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

那么我们就先跑一个最大生成树对吧,然后找两点之间路径的最小值

找路径最小值什么的主要是用一个在线的LCA

在维护f数组同时我们再加入一个d数组,d[u,i]表示从u开始向上2^i步里的最小值

然后就可以了~

代码量什么的略大,我写了160行左右

const     shuru='truck.in';
	  shuchu='truck.out';
	  maxlen=13;
type edge=record
		from,too,wei:longint;
		  end;
var	deep,father,headlist:array[0..10001] of longint;
	next,weight,t:array[0..20001] of longint;
	a:array[0..50001] of edge;
	vis:array[0..10001] of boolean;
	d,f:array[0..10001,0..13] of longint;
	step,num,x,y,z,now,i,j,k,n,m,q:longint;
	p:edge;
function min(a,b:longint):longint;
begin
	if a<b then exit(a);
	exit(b);
end;
procedure init;
begin
	assign(input,shuru);
	assign(output,shuchu);
	reset(input);
	rewrite(output);
	readln(n,m);
	for i:=1 to m do with a[i] do readln(from,too,wei);
	for i:=1 to n do begin father[i]:=i; headlist[i]:=-1; end;
end;
procedure qsort(l,r:longint);
var i,j,mid:longint;
begin
	i:=l; j:=r; mid:=a[(l+r) div 2].wei;
	repeat
		while (a[i].wei>mid) do inc(i);
		while (a[j].wei<mid) do dec(j);
		if i<=j then begin
						p:=a[i];
						a[i]:=a[j];
						a[j]:=p;
						inc(i); dec(j);
					 end;
	until i>j;
	if j>l then qsort(l,j);
	if i<r then qsort(i,r);
end;
function find(k:longint):longint;
var x,step:longint;
begin
	step:=k;
	while (step<>father[step]) do step:=father[step];
	while k<>step do
	begin
		x:=father[k];
		father[k]:=step;
		k:=x;
	end;
	exit(step);
end;
procedure merge(a,b:longint);
var fa1,fa2:longint;
begin
	fa1:=find(a); fa2:=find(b);
	father[fa2]:=fa1;
end;
procedure mit;
begin
	qsort(1,m);
	now:=1;
	for i:=1 to n-1 do
	begin
		x:=a[now].from; y:=a[now].too; z:=a[now].wei;
		while (find(x)=find(y)) do
		begin
			inc(now);
			if now>=m+1 then break;
			x:=a[now].from; y:=a[now].too; z:=a[now].wei;
		end;
		if now>=m+1 then break;
		merge(x,y);
		inc(num);
		next[num]:=headlist[x];
		headlist[x]:=num;
		weight[num]:=z;
		t[num]:=y;
		inc(num);
		next[num]:=headlist[y];
		headlist[y]:=num;
		weight[num]:=z;
		t[num]:=x;
	end;
end;
procedure dfs(u:longint);
var i:longint;
begin
	for i:=1 to maxlen do f[u,i]:=f[f[u,i-1],i-1];
	for i:=1 to maxlen do d[u,i]:=min(d[u,i-1],d[f[u,i-1],i-1]);
	i:=headlist[u];
	while i<>-1 do
	begin
		if (not(vis[t[i]])) then begin
									i:=next[i];
									continue;
								 end;
		vis[t[i]]:=false;
		f[t[i],0]:=u;
		d[t[i],0]:=weight[i];
		deep[t[i]]:=deep[u]+1;
		dfs(t[i]);
		i:=next[i];
	end;
end;
function ask(a,b:longint):longint;
var i,del:longint;
begin
	ask:=maxlongint;
	if deep[a]>deep[b] then begin
								step:=a;
								a:=b;
								b:=step;
							end;
	del:=deep[b]-deep[a];
	for i:=0 to maxlen do if (del and (1 shl i))<>0 then begin
															ask:=min(d[b,i],ask);
															b:=f[b,i];
														 end;
	if a<>b then begin
		for i:=maxlen downto 0 do
			if f[a,i]<>f[b,i] then begin
										ask:=min(ask,d[b,i]);
										ask:=min(ask,d[a,i]);
										a:=f[a,i];
										b:=f[b,i];
								   end;
		ask:=min(ask,d[a,0]);
		ask:=min(ask,d[b,0]);
				end;
end;
procedure main;
begin
	init;
	mit;
	fillchar(vis,sizeof(vis),true);
	for i:=1 to n do
		if vis[i] then begin
						deep[i]:=1;
                                                vis[i]:=false;
						dfs(i);
					   end;
	readln(q);
	for i:=1 to q do
	begin
		readln(x,y);
		if find(x)<>find(y) then writeln(-1)
							else writeln(ask(x,y));
	end;
	close(input);
	close(output);
end;
begin
	main;
end.


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值