BZOJ 4736 温暖会指引我们前行 LCT+最优生成树+并查集

题目链接:http://uoj.ac/problem/274

 

题意概述:

  没什么好概述的......概述了题意就知道怎么做了......我懒嘛

 

分析:

  就是用lct维护最大生成树。

  然后如果去UOJ上面交发现如果不用并查集判断连通性就要T?!

  然后我就默默改了并查集。。。(hash表并查集输入输出占据了一半的行数?!)

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<queue>
  8 #include<set>
  9 #include<map>
 10 #include<vector>
 11 #include<cctype>
 12 #define inf 1e9+5
 13 using namespace std;
 14 const int maxm=300005;
 15 
 16 int N,M;
 17 struct edge{ int u,v; }E[maxm];
 18 struct union_find{
 19     static const int maxn=100005;
 20     int pa[maxn],stk[maxn],top;
 21     void initial(int n){ for(int i=1;i<=n;i++) pa[i]=i; }
 22     int find(int x){
 23         while(x!=pa[x]) stk[++top]=x,x=pa[x];
 24         while(top) pa[stk[top--]]=x;
 25         return x;
 26     }
 27     bool judge(int x,int y){ return find(x)==find(y); }
 28     void merge(int x,int y){ pa[find(x)]=find(y); }
 29 }uf;
 30 struct Link_Cut_Tree{
 31     static const int maxn=400005;
 32     int ch[maxn][2],fa[maxn],sum[maxn],w[maxn],mn[maxn],t[maxn];
 33     bool rev[maxn];
 34     Link_Cut_Tree(){ mn[0]=inf; }
 35     void link(int x,int d,int y){ ch[x][d]=y,fa[y]=x; }
 36     bool isrt(int x){ return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; }
 37     void pushup(int now){
 38         sum[now]=sum[ch[now][0]]+sum[ch[now][1]]+w[now];
 39         mn[now]=min(t[now],min(mn[ch[now][0]],mn[ch[now][1]]));
 40     }
 41     void pushdown(int now){
 42         if(!rev[now]) return;
 43         rev[ch[now][0]]^=1,swap(ch[ch[now][0]][0],ch[ch[now][0]][1]);
 44         rev[ch[now][1]]^=1,swap(ch[ch[now][1]][0],ch[ch[now][1]][1]);
 45         rev[now]=0;
 46     }
 47     void rot(int x){
 48         int y=fa[x],z=fa[y];
 49         pushdown(y); pushdown(x);
 50         int d=x==ch[y][0];
 51         if(!isrt(y)) link(z,ch[z][1]==y,x); fa[x]=z;
 52         link(y,d^1,ch[x][d]);
 53         link(x,d,y);
 54         pushup(y); pushup(x);
 55     }
 56     void splay(int x){
 57         pushdown(x);
 58         while(!isrt(x)){
 59             int y=fa[x],z=fa[y];
 60             if(!isrt(y)) rot((ch[z][0]==y)==(ch[y][0]==x)?y:x);
 61             rot(x);
 62         }
 63     }
 64     void access(int x){
 65         int y=0;
 66         while(x){
 67             splay(x); ch[x][1]=y; pushup(x);
 68             y=x,x=fa[x];
 69         }
 70     }
 71     void mroot(int x){
 72         access(x); splay(x);
 73         rev[x]^=1,swap(ch[x][0],ch[x][1]);
 74     }
 75     void Link(int x,int y,int id,int w1,int w2){
 76         mroot(x); mroot(y);
 77         w[N+id]=sum[N+id]=w1,t[N+id]=mn[N+id]=w2;
 78         fa[x]=fa[y]=N+id;
 79     }
 80     void Cut(int id,int x,int y){
 81         mroot(N+id); access(N+id);
 82         splay(x); fa[x]=0;
 83         splay(y); fa[y]=0;
 84     }
 85     int query1(int x,int y){
 86         mroot(y); access(x); splay(x);
 87         return mn[x];
 88     }
 89     int query2(int x,int y){
 90         mroot(y); access(x); splay(x);
 91         return sum[x];
 92     }
 93 }lct;
 94 struct Hash{
 95     static const int maxn=300005;
 96     static const int mo=1000029;
 97     int np,first[mo],next[maxn],id[maxn],val[maxn];
 98     void ins(int p,int t){
 99         int i=t%mo;
100         next[++np]=first[i],first[i]=np;
101         id[np]=p,val[np]=t;
102     }
103     int find(int t){
104         int i=t%mo;
105         for(int p=first[i];p;p=next[p])
106             if(val[p]==t) return id[p];
107         return -1;
108     }
109 }hash;
110 
111 void _scanf(int &x)
112 {
113     x=0;
114     char c=getchar();
115     while(c<'0'||c>'9') c=getchar();
116     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
117 }
118 void _scanf(char *s)
119 {
120     int cnt=0;
121     char c=getchar();
122     while(!isalpha(c)) c=getchar();
123     while(isalpha(c)) s[cnt++]=c,c=getchar();
124     s[cnt]='\0';
125 }
126 int out_cnt,out[15];
127 void _printf(int x)
128 {
129     if(x<0) putchar('-'),x=-x;
130     out[++out_cnt]=x%10,x/=10;
131     while(x) out[++out_cnt]=x%10,x/=10;
132     while(out_cnt) putchar('0'+out[out_cnt--]);
133     putchar('\n');
134 }
135 void work()
136 {
137     _scanf(N);_scanf(M);
138     uf.initial(N);
139     for(int i=1;i<=N;i++) lct.t[i]=lct.mn[i]=inf;
140     char op[10];
141     int id,u,v,t,l,x;
142     for(int i=1;i<=M;i++){
143         _scanf(op);
144         if(op[0]=='f'){
145             _scanf(id);_scanf(u);_scanf(v);_scanf(t);_scanf(l);
146             u++,v++,id++;
147             E[id]=(edge){u,v};
148             hash.ins(id,t);
149             if(uf.judge(u,v)){
150                 x=lct.query1(u,v);
151                 if(x<t){
152                     x=hash.find(x);
153                     lct.Cut(x,E[x].u,E[x].v);
154                     lct.Link(u,v,id,l,t);
155                 }
156             }
157             else{
158                 lct.Link(u,v,id,l,t);
159                 uf.merge(u,v);
160             }
161         }
162         else if(op[0]=='m'){
163             _scanf(u);_scanf(v); u++,v++;
164             _printf(uf.judge(u,v)?lct.query2(u,v):-1);
165         }
166         else if(op[0]=='c'){
167             _scanf(id);_scanf(l); id++;
168             lct.splay(N+id);
169             lct.w[N+id]=l;
170         }
171     }
172 }
173 int main()
174 {
175     work();
176     return 0;
177 }
View Code

 

posted @ 2018-04-06 16:24  KKKorange  阅读(261)  评论(1编辑  收藏  举报