BZOJ3669 NOI2014魔法森林
按a从小到大排序,然后按b建图。
每次只需要找1~n中最大的b加当前的a计算答案即可。
这里还有一个小操作就是化边为点,把一条边的边权看做一个点的点权然后多连两条边。
By:大奕哥
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=4e5+10; 4 int fa[N],ma[N],pos[N],c[N][2],rev[N],s[N],n,m,ans=2e9,w[N]; 5 struct node{ 6 int x,y,a,b; 7 bool operator <(const node &b)const{ 8 return a<b.a; 9 } 10 }a[N]; 11 bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;} 12 void pushup(int x) 13 { 14 if(rev[x]) 15 { 16 rev[x]^=1;rev[c[x][0]]^=1;rev[c[x][1]]^=1; 17 swap(c[x][0],c[x][1]); 18 } 19 return; 20 } 21 void update(int x) 22 { 23 ma[x]=w[x];pos[x]=x; 24 if(ma[c[x][0]]>ma[x])ma[x]=ma[c[x][0]],pos[x]=pos[c[x][0]]; 25 if(ma[c[x][1]]>ma[x])ma[x]=ma[c[x][1]],pos[x]=pos[c[x][1]]; 26 return; 27 } 28 void rotate(int x) 29 { 30 int y=fa[x],z=fa[y],l,r; 31 l=c[y][1]==x;r=l^1; 32 if(!isroot(y))c[z][c[z][1]==y]=x; 33 fa[x]=z;fa[y]=x;fa[c[x][r]]=y; 34 c[y][l]=c[x][r];c[x][r]=y; 35 update(y);update(x); 36 } 37 void splay(int x) 38 { 39 int top=0,i; 40 for(i=x;!isroot(i);i=fa[i])s[++top]=i;s[++top]=i; 41 for(;top;top--)pushup(s[top]); 42 while(!isroot(x)) 43 { 44 int y=fa[x],z=fa[y]; 45 if(!isroot(y)) 46 { 47 if(c[y][0]==x^c[z][0]==y)rotate(x); 48 else rotate(y); 49 } 50 rotate(x); 51 } 52 return; 53 } 54 void access(int x) 55 { 56 int y=0; 57 while(x) 58 { 59 splay(x); 60 c[x][1]=y; 61 y=x;x=fa[x]; 62 } 63 } 64 void mroot(int x) 65 { 66 access(x);splay(x);rev[x]^=1; 67 } 68 void link(int x,int y) 69 { 70 mroot(x);fa[x]=y;splay(x); 71 } 72 void cut(int x,int y) 73 { 74 mroot(x);access(y);splay(y);c[y][0]=fa[x]=0; 75 } 76 int get(int x) 77 { 78 access(x);splay(x);while(c[x][0])x=c[x][0];return x; 79 } 80 int main() 81 { 82 scanf("%d%d",&n,&m); 83 for(int i=1;i<=m;++i) 84 { 85 scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].a,&a[i].b); 86 } 87 sort(a+1,a+1+m); 88 for(int i=1;i<=m;++i) 89 { 90 w[i+n]=a[i].b; 91 } 92 for(int i=1;i<=m;++i) 93 { 94 if(a[i].x==a[i].y)continue; 95 int fx=get(a[i].x),fy=get(a[i].y); 96 if(fx!=fy) 97 { 98 link(a[i].x,i+n);link(i+n,a[i].y); 99 } 100 else 101 { 102 mroot(a[i].x);access(a[i].y); 103 splay(a[i].y);int tmp=pos[c[a[i].y][0]]; 104 if(w[tmp]>a[i].b) 105 { 106 cut(tmp,a[tmp-n].x);cut(tmp,a[tmp-n].y); 107 link(a[i].x,n+i);link(a[i].y,n+i); 108 } 109 } 110 if(get(1)==get(n)) 111 { 112 mroot(1); 113 access(n); 114 splay(n); 115 ans=min(ans,a[i].a+ma[c[n][0]]); 116 } 117 } 118 if(ans!=2e9) 119 printf("%d\n",ans); 120 else puts("-1"); 121 return 0; 122 }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。