记录编号 160925 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOI 2014]魔法森林 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 3.160 s
提交时间 2015-04-29 21:47:02 内存使用 5.01 MiB
显示代码纯文本
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. using namespace std;
  6. const int INF=0x7fffffff/2;
  7. const int SIZET=150010,SIZEM=100010;
  8. int value[SIZET];
  9. class Node{
  10. public:
  11. int fa;
  12. int lc,rc;
  13. int mxid;
  14. bool rev;
  15. #define fa(x) Tree[x].fa
  16. #define lc(x) Tree[x].lc
  17. #define rc(x) Tree[x].rc
  18. #define mxid(x) Tree[x].mxid
  19. #define rev(x) Tree[x].rev
  20. }Tree[SIZET];
  21. bool Is_Root(int x){
  22. return lc(fa(x))!=x&&rc(fa(x))!=x;
  23. }
  24. void Push_Down(int x){
  25. if(rev(x)){
  26. rev(x)=false;
  27. swap(lc(x),rc(x));
  28. if(lc(x)) rev(lc(x))^=1;
  29. if(rc(x)) rev(rc(x))^=1;
  30. }
  31. }
  32. void Update(int x){
  33. mxid(x)=x;
  34. if(value[mxid(lc(x))]>value[mxid(x)]){mxid(x)=mxid(lc(x));}
  35. if(value[mxid(rc(x))]>value[mxid(x)]){mxid(x)=mxid(rc(x));}
  36. }
  37. void Zig(int x){//右旋
  38. int y=fa(x),z=fa(y);
  39. if(lc(z)==y) lc(z)=x;
  40. if(rc(z)==y) rc(z)=x;
  41. fa(x)=z;
  42. lc(y)=rc(x);fa(lc(y))=y;
  43. rc(x)=y;fa(y)=x;
  44. Update(y);Update(x);
  45. }
  46. void Zag(int x){//左旋
  47. int y=fa(x),z=fa(y);
  48. if(lc(z)==y) lc(z)=x;
  49. if(rc(z)==y) rc(z)=x;
  50. fa(x)=z;
  51. rc(y)=lc(x);fa(rc(y))=y;
  52. lc(x)=y;fa(y)=x;
  53. Update(y);Update(x);
  54. }
  55. void Splay(int x){//把x整到当前伸展树的根
  56. Push_Down(x);
  57. while(!Is_Root(x)){
  58. int y=fa(x),z=fa(y);
  59. Push_Down(z);Push_Down(y);Push_Down(x);
  60. if(Is_Root(y)){
  61. if(lc(y)==x) Zig(x);
  62. else Zag(x);
  63. break;
  64. }
  65. else if(lc(y)==x){
  66. if(lc(z)==y) Zig(y),Zig(x);
  67. else Zig(x),Zag(x);
  68. }
  69. else{
  70. if(rc(z)==y) Zag(y),Zag(x);
  71. else Zag(x),Zig(x);
  72. }
  73. }
  74. }
  75. void Access(int x){//把x到根路径连成伸展树
  76. int y=0;
  77. while(x){
  78. Splay(x);
  79. rc(x)=y;
  80. Update(x);
  81. y=x;
  82. x=fa(x);
  83. }
  84. }
  85. int Get_Root(int x){
  86. Access(x);
  87. Splay(x);
  88. while(lc(x)){
  89. Push_Down(x);
  90. x=lc(x);
  91. }
  92. Splay(x);
  93. return x;
  94. }
  95. bool Is_Connected(int x,int y){
  96. return Get_Root(x)==Get_Root(y);
  97. }
  98. void Make_Root(int x){
  99. Access(x);
  100. Splay(x);
  101. rev(x)^=1;
  102. }
  103. void Link(int x,int y){
  104. Make_Root(x);
  105. fa(x)=y;
  106. }
  107. void Cut(int x,int y){
  108. Make_Root(x);
  109. Access(y);
  110. Splay(y);
  111. fa(lc(y))=0;lc(y)=0;
  112. Update(y);
  113. }
  114. int Path_Query(int x,int y){
  115. Make_Root(x);
  116. Access(y);
  117. Splay(y);
  118. return mxid(y);
  119. }
  120. class Edge{
  121. public:
  122. int x,y,a,b;
  123. };
  124. bool operator < (const Edge &s,const Edge &t){
  125. if(s.a!=t.a) return s.a<t.a;
  126. return s.b<t.b;
  127. }
  128. int N,M;
  129. Edge edges[SIZEM];
  130. void Add_Edge(int k){
  131. Edge &e=edges[k];
  132. value[N+k]=e.b;
  133. Link(N+k,e.x);
  134. Link(N+k,e.y);
  135. }
  136. void Work(void){
  137. int ans=INF;
  138. for(int i=1;i<=M;i++){
  139. Edge &e=edges[i];
  140. if(!Is_Connected(e.x,e.y)) Add_Edge(i);
  141. else{
  142. int k=Path_Query(e.x,e.y);
  143. if(value[k]>e.b){
  144. Cut(k,edges[k-N].x);
  145. Cut(k,edges[k-N].y);
  146. Add_Edge(i);
  147. }
  148. }
  149. if(Is_Connected(1,N)){
  150. int k=Path_Query(1,N);
  151. ans=min(ans,e.a+value[k]);
  152. }
  153. }
  154. if(ans==INF) ans=-1;
  155. printf("%d\n",ans);
  156. }
  157. void Init(void){
  158. scanf("%d%d",&N,&M);
  159. for(int i=1;i<=M;i++)
  160. scanf("%d%d%d%d",&edges[i].x,&edges[i].y,&edges[i].a,&edges[i].b);
  161. sort(edges+1,edges+1+M);
  162. }
  163. int main(){
  164. freopen("magicalforest.in","r",stdin);
  165. freopen("magicalforest.out","w",stdout);
  166. Init();
  167. Work();
  168. return 0;
  169. }