[USACO 2014 Feb Silver && Gold] Roadblock

14 篇文章 0 订阅
4 篇文章 0 订阅

[题目大意]

每天早晨醒来,FJ穿过农场从他家的谷仓。该农场有N个场(1≤n≤250),由M条双向通路的连接(1≤M<=25000),每一条通路都有一个长度。FJ的房子是在1场,谷仓在N场,两个场之间没有冗余通路,按一个适当的顺序沿路径走,可以前往任何场。当从一个场到另一个,FJ总是选择组成的路径序列的总长度最小通路通过。农夫约翰的奶牛,总是没有好起来,决定妨碍他的早上行程。他们计划建造一堆干草捆在一个农场上的通路上,这样会使其长度加倍。奶牛要选择,使他们的工作能最大限度地增加FJ从家里到谷仓的途径的距离。请帮助奶牛决定如何能延长FJ的路线。

觉得自己最近代码正确率挺高的啊。。好几次都是一次提交都对。。

刚刚好像有个人在上面作死。。不怕掉RP?

首先我们先跑一个最短路出来。。

我们很容易可以yy出来,如果要延长它的路线,那么一定会在它的最短路上。。

不然没影响对伐。。

然后就枚举就好了233.

const shuru='rblock.in';
	  shuchu='rblock.out';
	  maxn=251;
	  maxm=50001;
	  qlong=maxn*50;
	  INF=1 shl 27;
var	d,headlist:array[0..maxn] of longint;
	next,t,w,weight:array[0..maxm] of longint;
	queue:array[0..qlong] of longint;
	inq:array[0..maxn] of boolean;
	re1,re2:array[0..maxn] of longint;
	map:array[0..maxn] of longint;
	p,front,finish,ans,data,i,j,x,y,z,num,k,n,m:longint;
procedure init;
begin
	readln(n,m);
	num:=-1;
	for i:=1 to n do headlist[i]:=-1;
	for i:=1 to m do
	begin
		readln(x,y,z);
		inc(num);
		next[num]:=headlist[x];
		headlist[x]:=num;
		t[num]:=y;
		weight[num]:=z;
		inc(num);
		next[num]:=headlist[y];
		headlist[y]:=num;
		t[num]:=x;
		weight[num]:=z;
	end;
end;
procedure spfa;
begin
	front:=0; finish:=1;
	fillchar(inq,sizeof(inq),false);
	for i:=2 to n do d[i]:=INF;
	d[1]:=0;
	queue[1]:=1; inq[1]:=true;
	while front<>finish do
	begin
		inc(front);
		if front>qlong then front:=front-qlong;
		x:=queue[front];
		inq[x]:=false;
		i:=headlist[x];
		while i<>-1 do
		begin
			if d[t[i]]>d[x]+weight[i] then begin
											d[t[i]]:=d[x]+weight[i];
											re1[t[i]]:=x;
											re2[t[i]]:=i;
											if not(inq[t[i]]) then begin
																	inc(finish);
																	if finish>qlong then finish:=finish-qlong;
																	queue[finish]:=t[i];
																	inq[t[i]]:=true;
																   end;
										   end;
			i:=next[i];
		end;
	end;
	data:=d[n];
	num:=0;
	i:=n;
	while (i<>1) do
	begin
		inc(num);
		map[num]:=re2[i];
		i:=re1[i];
	end;
end;
function max(a,b:longint):longint;
begin
	if a>b then exit(a);
	exit(b);
end;
procedure main;
begin
	init;
	spfa;
	for p:=1 to num do
	begin
		w:=weight;
		w[map[p]]:=w[map[p]]*2;
		w[map[p] xor 1]:=w[map[p] xor 1]*2;front:=0; finish:=1;
		fillchar(inq,sizeof(inq),false);
		for i:=2 to n do d[i]:=INF;
		d[1]:=0;
		queue[1]:=1; inq[1]:=true;
		while front<>finish do
		begin
			inc(front);
			if front>qlong then front:=front-qlong;
			x:=queue[front];
			inq[x]:=false;
			i:=headlist[x];
			while i<>-1 do
			begin
				if d[t[i]]>d[x]+w[i] then begin
												d[t[i]]:=d[x]+w[i];
												if not(inq[t[i]]) then begin
																		inc(finish);
																		if finish>qlong then finish:=finish-qlong;
																		queue[finish]:=t[i];
																		inq[t[i]]:=true;
																	   end;
											  end;
				i:=next[i];
			end;
		end;
		ans:=max(ans,d[n]-data);
	end;
	writeln(ans);
end;
begin
	main;
end.


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值