UOJ274 [清华集训2016] 温暖会指引我们前行 【LCT】【最大生成树】
题目分析:
差评,最大生成树裸题。hack数据还卡常。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 402000; 5 6 struct LCT{ 7 int fa[maxn],lazy[maxn],ch[maxn][2],d1[maxn],d2[maxn]; 8 int val[maxn],tot[maxn],num; 9 stack<int> sta; 10 void push_up(int now){ 11 val[now] = min(d1[now],min(val[ch[now][0]],val[ch[now][1]])); 12 tot[now] = d2[now] + tot[ch[now][0]] + tot[ch[now][1]]; 13 } 14 void push_down(int now){ 15 if(lazy[now]){ 16 swap(ch[now][0],ch[now][1]); 17 lazy[now]=0; 18 lazy[ch[now][0]] ^= 1; lazy[ch[now][1]] ^= 1; 19 lazy[0] = 0; 20 } 21 } 22 int is_root(int now){return !(ch[fa[now]][0]==now||ch[fa[now]][1]==now);} 23 void r0(int now,int dr){ 24 int ff = fa[now],gf = fa[ff],son = ch[now][dr]; 25 int flag = is_root(ff); 26 ch[ff][dr^1] = son; fa[son] = ff; 27 ch[now][dr] = ff; fa[ff] = now; 28 fa[now] = gf; 29 if(!flag){if(ch[gf][0] == ff) ch[gf][0] = now; else ch[gf][1] = now;} 30 push_up(ff); push_up(now); 31 fa[0] = 0;ch[0][0] = ch[0][1] = 0; 32 } 33 void splay(int now){ 34 int pp = now; 35 while(!is_root(pp)) sta.push(pp),pp = fa[pp]; 36 sta.push(pp); 37 while(!sta.empty()) push_down(sta.top()),sta.pop(); 38 while(!is_root(now)){ 39 if(is_root(fa[now])){ 40 if(ch[fa[now]][0] == now) r0(now,1); else r0(now,0); 41 }else{ 42 int ff = fa[now],gf = fa[ff]; 43 int alpha = ch[gf][0]==ff,beta = ch[ff][0]==now; 44 if(alpha^beta) r0(now,beta),r0(now,alpha); 45 else r0(ff,alpha),r0(now,beta); 46 } 47 } 48 } 49 void access(int now){ 50 splay(now);ch[now][1] = 0;push_up(now); 51 while(fa[now]){ 52 int nxt=fa[now];splay(nxt);ch[nxt][1]=now; push_up(nxt); now=nxt; 53 } 54 } 55 void make_root(int now){ 56 access(now); 57 splay(now); 58 lazy[now] ^= 1; 59 } 60 void cut(int u,int v){ 61 make_root(u); access(v); splay(u); 62 fa[v] = 0; 63 if(ch[u][0] == v) ch[u][0] = 0; else ch[u][1] = 0; 64 push_up(u); 65 } 66 void link(int u,int v){make_root(u); fa[u] = v;} 67 int lft(int dt){ 68 splay(dt); 69 if(lazy[dt]) push_down(dt); 70 while(ch[dt][0]){ 71 dt = ch[dt][0]; 72 if(lazy[dt]) push_down(dt); 73 } 74 return dt; 75 } 76 int find_min(int now){ 77 splay(now); 78 while(d1[now] != val[now]){ 79 if(val[ch[now][0]] == val[now]) now = ch[now][0]; 80 else now = ch[now][1]; 81 } 82 return now; 83 } 84 }T; 85 86 int n,m,pre[maxn]; 87 88 struct edge{int from,to,tmp,len;}edges[maxn]; 89 90 char str[7]; 91 92 int found(int x){ 93 int rx = x; while(pre[rx] != rx) rx = pre[rx]; 94 while(pre[x]!=rx){int tt = x; pre[x] = rx; x = tt;} 95 return rx; 96 } 97 98 void work(){ 99 T.d1[0] = 2e9;T.val[0] = 2e9;T.d2[0] = 0; 100 for(int i=1;i<=n;i++){T.num++;T.d1[i] = 2e9; T.val[i] = 2e9; pre[i] = i;} 101 for(int i=1;i<=m;i++){ 102 scanf("%s",str); 103 if(str[0] == 'f'){ 104 int id;scanf("%d",&id); 105 scanf("%d%d",&edges[id].from,&edges[id].to); 106 scanf("%d%d",&edges[id].tmp,&edges[id].len); 107 edges[id].from++;edges[id].to++; 108 T.d1[n+id+1] = edges[id].tmp; T.d2[n+id+1] = edges[id].len; 109 T.val[n+id+1] = edges[id].tmp; T.tot[n+id+1] = edges[id].len; 110 T.make_root(edges[id].from); 111 T.access(edges[id].to); 112 int pd = T.lft(edges[id].to); 113 if(pd == edges[id].from){ 114 if(T.val[edges[id].to] > edges[id].tmp) continue; 115 int pla = T.find_min(edges[id].to); 116 T.make_root(pla);T.cut(pla,edges[pla-n-1].from); 117 T.cut(pla,edges[pla-n-1].to); 118 } 119 T.link(edges[id].from,n+id+1);T.link(edges[id].to,n+id+1); 120 pre[found(edges[id].from)] = found(edges[id].to); 121 }else{ 122 if(str[0] == 'm'){ 123 int u,v; scanf("%d%d",&u,&v); v++;u++; 124 if(found(u) != found(v)){puts("-1");continue;} 125 T.make_root(u); T.access(v); T.splay(v); 126 printf("%d\n",T.tot[v]); 127 }else{ 128 int id,l; scanf("%d%d",&id,&l); 129 T.make_root(n+id+1); T.d2[n+id+1] = l; 130 T.push_up(n+id+1); 131 } 132 } 133 } 134 } 135 136 int main(){ 137 scanf("%d%d",&n,&m); 138 work(); 139 return 0; 140 }