BZOJ 4736 温暖会指引我们前行 LCT+最优生成树+并查集
题目链接:http://uoj.ac/problem/274
题意概述:
没什么好概述的......概述了题意就知道怎么做了......我懒嘛
分析:
就是用lct维护最大生成树。
然后如果去UOJ上面交发现如果不用并查集判断连通性就要T?!
然后我就默默改了并查集。。。(hash表并查集输入输出占据了一半的行数?!)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }