NOI2014魔法森林
Orz 神奇性质 LCT板子
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 50010 4 #define RG register 5 #define IL inline 6 #define rep(a,b,c) for(register int (a)=(b);(a)<=(c);++(a)) 7 #define INF (1<<30) 8 IL bool isitdigit(char c){ return c>='0'&&c<='9'; } 9 IL int read() 10 { 11 RG int s;RG char c; 12 while(!isitdigit(c=getchar())); 13 for(s=c-'0';isitdigit(c=getchar());s=(s<<1)+(s<<3)+c-'0'); 14 return s; 15 } 16 IL int minify(int & a,int b){ return a<=b? a:a=b; } 17 IL void swapt(int & a,int &b){ RG int t=a;a=b,b=t; } 18 19 20 int n,m,ans=INF; 21 22 23 int findset[N]; 24 int find(int x){ return x==findset[x]? x:findset[x]=find(findset[x]); } 25 IL int judge(int a,int b){ return find(a)==find(b); } 26 IL int combine(int a,int b){ findset[findset[a]]=findset[b]; } 27 28 29 struct edge 30 { 31 int f,t,a,b,e; 32 edge(int ff=0,int tt=0,int aa=0,int bb=0,int ee=0):f(ff),t(tt),a(aa),b(bb),e(ee){} 33 const bool operator < (const edge another) 34 const{ return a<another.a; } 35 }eg[2*N]; 36 37 38 int fa[3*N],son[3*N][2],mx[3*N],rev[N*3],tot; 39 IL bool isroot(int o){ return son[fa[o]][1]!=o&&son[fa[o]][0]!=o; } 40 IL int side(int o){ return son[fa[o]][1]==o; } 41 IL void add(int f,int d,int s){ fa[s]=f,son[f][d]=s; } 42 IL void reverse(int o) 43 { 44 if(!o) return;rev[o]^=1; 45 swapt(son[o][1],son[o][0]); 46 } 47 IL void pushdown(int o) 48 { 49 if(!rev[o])return;rev[o]=0; 50 reverse(son[o][1]);reverse(son[o][0]); 51 } 52 IL void pushup(int o) 53 { 54 if(o>n) mx[o]=o-n; else mx[o]=0; 55 if(son[o][1]) mx[o]=eg[mx[o]].b>eg[mx[son[o][1]]].b? mx[o]:mx[son[o][1]]; 56 if(son[o][0]) mx[o]=eg[mx[o]].b>eg[mx[son[o][0]]].b? mx[o]:mx[son[o][0]]; 57 } 58 IL int newnode(int t){ mx[++tot]=t;return tot; } 59 IL void ronate(int o) 60 { 61 RG int f=fa[o],g=fa[f],d=side(o); 62 if(isroot(f)) fa[o]=g;else add(g,side(f),o); 63 add(f,d,son[o][d^1]);add(o,d^1,f); 64 pushup(f);pushup(o); 65 } 66 IL void splay(int o) 67 { 68 static int que[2*N],top;que[top=1]=o; 69 for(RG int p=o;!isroot(p);p=fa[p]) que[++top]=fa[p]; 70 for(RG int p=top;p;--p) pushdown(que[p]); 71 for(RG int f;!isroot(o);ronate(o)) 72 if(!isroot(f=fa[o])) 73 ronate(side(o)^side(f)? o:f); 74 } 75 IL void aces(int o){ for(RG int f=0;o;son[o][1]=f,pushup(o),f=o,o=fa[o]) splay(o); } 76 IL void makeroot(int o){ aces(o);splay(o);reverse(o); } 77 IL void link(int a,int b){ makeroot(a);fa[a]=b; } 78 IL void cut(int a,int b){ makeroot(a);aces(b);splay(a);son[a][1]=fa[b]=0;pushup(a); } 79 IL int query(int a,int b){ makeroot(a);aces(b);splay(a);return mx[a]; } 80 81 82 int main() 83 { 84 freopen("magicalforest.in","r",stdin); 85 freopen("magicalforest.out","w",stdout); 86 tot=n=read(),m=read(); 87 rep(i,1,m) 88 { 89 RG int f=read(),t=read(),a=read(),b=read(); 90 eg[i]=(edge){f,t,a,b,0}; 91 } 92 rep(i,1,n) findset[i]=i; 93 sort(eg+1,eg+m+1); 94 ans=INF; 95 rep(i,1,m) 96 { 97 RG int res=INF; 98 RG edge & now=eg[i];now.e=newnode(i); 99 if(now.f==now.t) continue; 100 if(judge(now.f,now.t)) 101 { 102 RG edge & temp=eg[query(now.f,now.t)]; 103 if(temp.b>=now.b) 104 { 105 cut(temp.f,temp.e); 106 cut(temp.e,temp.t); 107 link(now.f,now.e); 108 link(now.e,now.t); 109 } 110 } 111 else 112 { 113 combine(now.f,now.t); 114 link(now.f,now.e); 115 link(now.e,now.t); 116 } 117 if(judge(1,n)) 118 { 119 RG edge& temp=eg[query(1,n)]; 120 res=now.a+temp.b; 121 } 122 minify(ans,res); 123 } 124 if(ans==INF) printf("-1"); 125 else printf("%d",ans); 126 return 0; 127 }