3669: [Noi2014]魔法森林

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 106  Solved: 62
[Submit][Status]

Description

为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士。魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M。初始时小E同学在号节点1,隐士则住在号节点N。小E需要通过这一片魔法森林,才能够拜访到隐士。

魔法森林中居住了一些妖怪。每当有人经过一条边的时候,这条边上的妖怪就会对其发起攻击。幸运的是,在号节点住着两种守护精灵:A型守护精灵与B型守护精灵。小E可以借助它们的力量,达到自己的目的。

只要小E带上足够多的守护精灵,妖怪们就不会发起攻击了。具体来说,无向图中的每一条边Ei包含两个权值Ai与Bi。若身上携带的A型守护精灵个数不少于Ai,且B型守护精灵个数不少于Bi,这条边上的妖怪就不会对通过这条边的人发起攻击。当且仅当通过这片魔法森林的过程中没有任意一条边的妖怪向小E发起攻击,他才能成功找到隐士。

由于携带守护精灵是一件非常麻烦的事,小E想要知道,要能够成功拜访到隐士,最少需要携带守护精灵的总个数。守护精灵的总个数为A型守护精灵的个数与B型守护精灵的个数之和。

Input

第1行包含两个整数N,M,表示无向图共有N个节点,M条边。 接下来M行,第行包含4个正整数Xi,Yi,Ai,Bi,描述第i条无向边。其中Xi与Yi为该边两个端点的标号,Ai与Bi的含义如题所述。 注意数据中可能包含重边与自环。

Output

输出一行一个整数:如果小E可以成功拜访到隐士,输出小E最少需要携带的守护精灵的总个数;如果无论如何小E都无法拜访到隐士,输出“-1”(不含引号)。

Sample Input

【输入样例1】
4 5
1 2 19 1
2 3 8 12
2 4 12 15
1 3 17 8
3 4 1 17
【输入样例2】
3 1
1 2 1 1

Sample Output

【输出样例1】

32
【样例说明1】
如果小E走路径1→2→4,需要携带19+15=34个守护精灵;
如果小E走路径1→3→4,需要携带17+17=34个守护精灵;
如果小E走路径1→2→3→4,需要携带19+17=36个守护精灵;
如果小E走路径1→3→2→4,需要携带17+15=32个守护精灵。
综上所述,小E最少需要携带32个守护精灵。
【输出样例2】
-1
【样例说明2】
小E无法从1号节点到达3号节点,故输出-1。

HINT

2<=n<=50,000

0<=m<=100,000

1<=ai ,bi<=50,000

Source

题解:

卡时真是一件痛苦的事儿。。考场上肯定卡不出来。。。

考场上怎么就sb的去枚举a,二分b,在spfa呢?更直观的想法不就是枚举a做mst吗?脑袋短路了。。。

正解是LCT,蒟蒻不会,先spfa水过。。

枚举a,做spfa即可,但这样只有30分,考虑各种优化:

1.每次枚举的时候 d 数组不用清空,如果 d[n]值发生了变化,一定走了一条当前枚举的 a 的上限,则每次用 d [n]+xx 来更新答案,如果没发生变化,也不会影响答案,因为xx是递增的

2.如果这样直接做的话会是答案错误,这是为什么?

  这是因为在加入了一条新边之后,不一定能更新从 1 出发的点,所以其他点就不会被加入队列,这条边就没用被用到!

  所以我们应当在枚举到一条边的时候,将这条边的两端打标记,spfa从这些有标记的点出发即可

3.发现TLE。。。

   如果打印出ans的变化值可以发现,在开始很长时间内ans都是 inf,也就是说 1 与 n 都不连通

   这样我们可以从小到大加入边,用并查集维护连通性,直到 1 与 n 第一次连通时,我们开始做 spfa,这样可以省掉一些无用的过程

综合以上3点,终于AC。。。

代码:

1.考场35分(真是RP啊。。。)

  1 const inf=maxlongint>>2;maxn=100000+10;
  2 type node=record
  3      from,go,next,v1,v2:longint;
  4      end;
  5 var a,b,d1,d2,head,fa:array[0..maxn] of longint;
  6     q:array[0..10*maxn] of longint;
  7     e:array[0..maxn*2] of node;
  8     v:array[0..maxn] of boolean;
  9     i,j,xx,yy,ll,tot,rr,x,y,point,mid:longint;
 10     ans,n,m:int64;
 11     function find(x:longint):longint;
 12      begin
 13      if fa[x]<>x then fa[x]:=find(fa[x]);
 14      exit(fa[x]);
 15      end;
 16     function max(x,y:longint):longint;
 17      begin
 18      if x>y then exit(x) else exit(y);
 19      end;
 20 procedure sort1(l,r:longint);
 21  var i,j,x,y:longint;
 22  begin
 23  i:=l;j:=r;x:=a[(i+j)>>1];
 24  repeat
 25   while a[i]>x do inc(i);
 26   while a[j]<x do dec(j);
 27   if i<=j then
 28    begin
 29    y:=a[i];a[i]:=a[j];a[j]:=y;
 30    inc(i);dec(j);
 31    end;
 32  until i>j;
 33  if i<r then sort1(i,r);
 34  if j>l then sort1(l,j);
 35  end;
 36 procedure sort2(l,r:longint);
 37  var i,j,x,y:longint;
 38  begin
 39  i:=l;j:=r;x:=b[(i+j)>>1];
 40  repeat
 41   while b[i]<x do inc(i);
 42   while b[j]>x do dec(j);
 43   if i<=j then
 44    begin
 45    y:=b[i];b[i]:=b[j];b[j]:=y;
 46    inc(i);dec(j);
 47    end;
 48  until i>j;
 49  if i<r then sort2(i,r);
 50  if j>l then sort2(l,j);
 51  end;
 52 procedure insert(x,y,z,w:longint);
 53  begin
 54  inc(tot);
 55  with e[tot] do
 56   begin
 57   from:=x;go:=y;next:=head[x];head[x]:=tot;v1:=z;v2:=w;
 58   end;
 59  end;
 60 procedure spfa;
 61  var i,x,y,h,t,tmp1,tmp2:longint;
 62  begin
 63  for i:=1 to n do d1[i]:=inf;
 64  for i:=1 to n do d2[i]:=inf;
 65  fillchar(v,sizeof(v),false);
 66  h:=0;t:=1;q[1]:=1;d1[1]:=0;d2[1]:=0;
 67  while h<t do
 68   begin
 69   inc(h);
 70   x:=q[h];v[x]:=false;
 71   i:=head[x];
 72   while i<>0 do
 73    begin
 74    y:=e[i].go;
 75    tmp1:=max(d1[x],e[i].v1);
 76    tmp2:=max(d2[x],e[i].v2);
 77    if (tmp1<=xx) and (tmp2<=yy) and (tmp2<d2[y]) then
 78     begin
 79     d1[y]:=tmp1;d2[y]:=tmp2;
 80     if not(v[y]) then
 81      begin
 82      v[y]:=true;
 83      inc(t);q[t]:=y;
 84      end;
 85     end;
 86    i:=e[i].next;
 87    end;
 88   end;
 89  end;
 90 procedure init;
 91  begin
 92  readln(n,m);
 93  for i:=1 to n do fa[i]:=i;
 94  for i:=1 to m do
 95   begin
 96   readln(x,y,a[i],b[i]);
 97   xx:=find(x);yy:=find(y);
 98   if xx<>yy then fa[xx]:=yy;
 99   insert(x,y,a[i],b[i]);insert(y,x,a[i],b[i]);
100   end;
101  sort1(1,m);
102  sort2(1,m);
103  end;
104 procedure work1;
105  begin
106  xx:=a[1];point:=1;
107  while true do
108   begin
109   ll:=1;rr:=m;
110   while ll<rr do
111    begin
112    mid:=(ll+rr)>>1;
113    yy:=b[mid];
114    spfa;
115    if d2[n]<>inf then rr:=mid else ll:=mid+1;
116    end;
117   inc(point);
118   while (point<=m) and (d1[n]<a[point]) do inc(point);
119   if point>m then break;
120   xx:=a[point];
121   if d1[n]+d2[n]<ans then ans:=d1[n]+d2[n];
122   end;
123  writeln(ans);
124  end;
125 procedure work2;
126  begin
127  for i:=1 to 100 do
128   begin
129    xx:=random(a[1])+1;
130    yy:=random(b[m])+1;
131    spfa;
132    if d1[n]+d2[n]<ans then ans:=d1[n]+d2[n];
133   end;
134  writeln(ans);
135  end;
136 begin
137  assign(input,'forest.in');assign(output,'forest.out');
138  reset(input);rewrite(output);
139  init;
140  ans:=inf;
141  if find(1)<>find(n) then writeln('-1') else if n*m*16<50000000 then work1 else work2;
142  close(input);close(output);
143 end.   
View Code

相关文章: