5818. 【NOIP提高A组模拟2018.8.15】 做运动

Description

一天,Y 君在测量体重的时候惊讶的发现,由于常年坐在电脑前认真学习,她的体重有了突 飞猛进的增长。
幸好 Y 君现在退役了,她有大量的时间来做运动,她决定每天从教学楼跑到食堂来减肥。
Y 君将学校中的所有地点编号为 1 到 n,其中她的教学楼被编号为 S,她的食堂被编号为 T, 学校中有 m 条连接两个点的双向道路,保证从任意一个点可以通过道路到达学校中的所有点。
然而 Y 君不得不面临一个严峻的问题,就是天气十分炎热,如果 Y 君太热了,她就会中暑。 于是 Y 君调查了学校中每条路的温度 t,及通过一条路所需的时间 c。Y 君在温度为 t 的地 方跑单位时间,就会使她的热量增加 t。
由于热量过高 Y 君就会中暑,而且 Y 君也希望在温度较低的路上跑,她希望在经过的所有 道路中最高温度最低的前提下,使她到达食堂时的热量最低 (从教学楼出发时,Y 君的热量为 0)。
请你帮助 Y 君设计从教学楼到食堂的路线,以满足她的要求。你只需输出你设计的路线中所 有道路的最高温度和 Y 君到达食堂时的热量。
 

Input

第一行由一个空格隔开的两个正整数 n, m,代表学校中的地点数和道路数。
接下来 m 行,每行由一个空格隔开的四个整数 a, b, t, c 分别代表双向道路的两个端点,温度 和通过所需时间.
最后一行由一个空格隔开的两个正整数 S, T,代表教学楼和食堂的编号。
注意:输入数据量巨大,请使用快速的读入方式。
 

Output

一行由一个空格隔开的两个整数,分别代表最高温度和热量。 
 

Solution

考虑将所有边按温度从小到大排序加入图中,同时用并查集维护 S 和 T 的连通性。

如果加入某些边之后 S 和 T 联通了,那么跑一遍 S 到 T 的最短路即可得到答案。

注意温度相等的边要一起加入图中。 时间复杂度 O(m log m)。

代码

  1 type
  2   arr=record
  3     x,y,next:longint;
  4     w:int64;
  5   end;
  6 var
  7   n,m,nm,q,z,maxt:longint;
  8   a:array [0..2000001] of arr;
  9   x,y,t,c:array [0..1000001] of longint;
 10   fa,ls,list,v:array [0..500001] of longint;
 11   d:array [0..500001] of int64;
 12 procedure init;
 13 var
 14   i:longint;
 15 begin
 16   readln(n,m);
 17   for i:=1 to m do
 18     readln(x[i],y[i],t[i],c[i]);
 19   readln(q,z);
 20 end;
 21 
 22 procedure qsort(l,r:longint);
 23 var
 24   mid,i,j,k:longint;
 25 begin
 26   if l>r then exit;
 27   i:=l; j:=r;
 28   mid:=t[(l+r) div 2];
 29   repeat
 30     while t[i]<mid do inc(i);
 31     while t[j]>mid do dec(j);
 32     if i<=j then
 33       begin
 34         k:=x[i]; x[i]:=x[j]; x[j]:=k;
 35         k:=y[i]; y[i]:=y[j]; y[j]:=k;
 36         k:=t[i]; t[i]:=t[j]; t[j]:=k;
 37         k:=c[i]; c[i]:=c[j]; c[j]:=k;
 38         inc(i); dec(j);
 39       end;
 40   until i>j;
 41   qsort(i,r);
 42   qsort(l,j);
 43 end;
 44 
 45 procedure add(xx,yy,zz:longint);
 46 begin
 47   inc(nm);
 48   a[nm].x:=xx; a[nm].y:=yy; a[nm].w:=zz;
 49   a[nm].next:=ls[xx]; ls[xx]:=nm;
 50 end;
 51 
 52 function get(x:longint):longint;
 53 begin
 54   if (fa[x]=0) or (fa[x]=x) then exit(x);
 55   fa[x]:=get(fa[x]);
 56   exit(fa[x]);
 57 end;
 58 
 59 function max(o,p:longint):longint;
 60 begin
 61   if o>p then exit(o);
 62   exit(p);
 63 end;
 64 
 65 procedure main;
 66 var
 67   i,tt,kk:longint;
 68 begin
 69   fillchar(fa,sizeof(fa),0);
 70   nm:=0; i:=1; maxt:=0;
 71   while i<=m do
 72     begin
 73       maxt:=max(maxt,t[i]);
 74       while t[i]=t[i+1] do
 75         begin
 76           add(x[i],y[i],t[i]*c[i]);
 77           add(y[i],x[i],t[i]*c[i]);
 78           tt:=get(x[i]); kk:=get(y[i]);
 79           fa[tt]:=kk;
 80           inc(i);
 81         end;
 82       add(x[i],y[i],t[i]*c[i]);
 83       add(y[i],x[i],t[i]*c[i]);
 84       tt:=get(x[i]); kk:=get(y[i]);
 85       fa[tt]:=kk;
 86       if get(q)=get(z) then break;
 87       inc(i);
 88     end;
 89 end;
 90 
 91 procedure spfa(xx:longint);
 92 var
 93   head,tail,i:longint;
 94 begin
 95   for i:=0 to 500001 do
 96     d[i]:=10000000000000000;
 97   head:=0; tail:=1;
 98   d[xx]:=0; v[xx]:=1; list[1]:=xx;
 99   repeat
100     inc(head);
101     i:=ls[list[head]];
102     while i<>0 do
103       begin
104         if d[a[i].x]+a[i].w<d[a[i].y] then
105           begin
106             d[a[i].y]:=d[a[i].x]+a[i].w;
107             if v[a[i].y]=0 then
108               begin
109                 v[a[i].y]:=1;
110                 inc(tail);
111                 list[tail]:=a[i].y;
112               end;
113           end;
114         i:=a[i].next;
115       end;
116     v[list[head]]:=0;
117   until head>tail;
118 end;
119 
120 begin
121   assign(input,'running.in');
122   assign(output,'running.out');
123   reset(input);
124   rewrite(output);
125   init;
126   qsort(1,m);
127   main;
128   spfa(q);
129   writeln(maxt,' ',d[z]);
130   close(input);
131   close(output);
132 end.

猜你喜欢

转载自www.cnblogs.com/zyx-crying/p/9482473.html
今日推荐