上学的道路 TYVJ1310

题目连接:http://new.tyvj.cn/Problem_Show.aspx?id=1310

主要是求2对点的最短路的公共部分最大是多少。

先瞎搞求出4个点的单源最短路。dij和spfa都可以。

然后对于任意两点i,j

如果d[x1,i]+d[y1,i]=d[x1,y1] 并且 d[x1,j]+d[y1,j]=d[x1,y1]  并且d[x2,i]+d[y2,i])=d[x2,y2]) 且 d[x2,j]+d[y2,j])=d[x2,y2] 

那么就可以判定I,J之间的在这两对点的最短路的公共部分,那么中间的那段部分就是公共长度了。


var
  x,y,x1,y1,x2,y2,ans,aa,i,j,k,z,n,m,tot:longint;
  v:array[-10..1600] of boolean;
  q:array[-10..1500000] of longint;
  d:array[-10..5,-10..1600] of longint;
  next,a,c:array[-10..600005] of longint;
  b:array[-10..1600] of longint;
procedure spfa(k,o:longint);
  var
    i,h,t,x,y,z,p:longint;
  begin
    for i:=1 to n do
	  d[k,i]:=999999999;
	d[k,o]:=0;

	h:=1;
	t:=1;
	q[h]:=o;
	fillchar(v,sizeof(v),true);
	v[o]:=false;
	while h<=t do
	  begin
	    x:=q[h];
		p:=b[x];
		while p<>0 do
		  begin
		    y:=c[p];
			z:=a[p];
			if (d[k,x]+z)<d[k,y] then
			  begin
			    d[k,y]:=d[k,x]+z;
				if v[y] then
				  begin
				    v[y]:=false;
					t:=t+1;
					q[t]:=y;
				  end;
			  end;
			p:=next[p];
		  end;
	    h:=h+1;
		v[x]:=true;
	  end;
  end;

function check(k,y,z:longint):boolean;
  begin
    if ((d[1,k]+d[2,y]+z)=d[1,y1]) and ((d[3,k]+d[4,y]+z)=d[3,y2]) then exit(true);
    if ((d[1,k]+d[2,y]+z)=d[1,y1]) and ((d[3,y]+d[4,k]+z)=d[3,y2]) then exit(true);
    exit(false);
  end;
function try(k:longint):longint;
  var
    t,p,x,y,z:longint;
  begin
    t:=0;
    v[k]:=false;
    p:=b[k];
	y:=c[p];
	z:=a[p];
	while p<>0 do
	  begin
	    if v[y] then
                  if check(k,y,z)  then
		    begin
			  x:=try(y)+z;
			  if x>ans then ans:=x;
			  if x>t then t:=x;
			end
		  else
		    if (d[1,k]+d[2,y]+z)=d[1,y1] then begin
		      x:=try(y);
			  if x>ans then ans:=x;
			end;
	    p:=next[p];
		y:=c[p];
	    z:=a[p];
	  end;
	v[k]:=true;
        if t>0 then exit(t) else exit(0);
  end;

begin
  read(n,m,x1,y1,x2,y2);
  tot:=0;
  for i:=1 to m do
    begin
	  read(x,y,z);
	  tot:=tot+1;
	  next[tot]:=b[x];
	  b[x]:=tot;
	  a[tot]:=z;
	  c[tot]:=y;

	  tot:=tot+1;
	  next[tot]:=b[y];
	  b[y]:=tot;
	  a[tot]:=z;
	  c[tot]:=x;

	end;
  spfa(1,x1);

  spfa(2,y1);
  spfa(3,x2);
  spfa(4,y2);
  fillchar(v,sizeof(v),true);
  ans:=0;
  for i:=1 to n do
    for j:=1 to n do
	  if ((d[1,i]+d[2,i])=d[1,y1]) and ((d[1,j]+d[2,j])=d[1,y1]) then
	    if ((d[3,i]+d[4,i])=d[3,y2]) and ((d[3,j]+d[4,j])=d[3,y2]) then
		  begin
	        x:=abs(d[1,i]-d[1,j]);
		    if x>ans then ans:=x;
		  end;	 
  writeln(ans);
end.

Oct_gap 201说得对。。
我太垃圾了
这个题因为数组开小了弄了半天。
我太垃圾了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值