您的位置:首页 > 理论基础 > 计算机网络

[ZJOI2012]网络 解题报告

2016-03-27 15:44 591 查看
这题还是非常奇怪的,在考试的时候做了这题的弱化版,去了求最值。

这道题要求维护一坨链,显然是可以直接上splay的,所以我考试的时候直接写了splay,结果因为两个bug调了5个小时。

求最值的话,当然也可以直接上splay。。但是那样的话很麻烦,因为没法在端点加点,所以要很复杂的讨论。直接用lct的话就好很多,但是用lct维护一坨链实在是很奇怪。。

而且这题的数据很难生成,tm拍都没法拍。。我实在是懒了,就直接下了数据。我也不想为自己解释。

通过这题我发现我的代码能力急需提高啊。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#include<algorithm>
#include<cmath>
const int N=1e4+5,M=1e5+5,C=10+5,K=1e5+5;
struct LS{
int ch[2],fa;
int v,max;
bool flag;
}lct[N*C];
void out(int node){
printf("%d:ch[0]=%d,ch[1]=%d,fa=%d,v=%d,max=%d\n",node,lct[node].ch[0],lct[node].ch[1],lct[node].fa,lct[node].v,lct[node].max);
}
void pushup(int node){
lct[node].max=max(lct[node].v,max(lct[lct[node].ch[0]].max,lct[lct[node].ch[1]].max));
}
void paint(int node){
if(node){
lct[node].flag^=1;
swap(lct[node].ch[0],lct[node].ch[1]);
}
}
void pushdown(int node){
if(lct[node].flag){
//printf("pushdown ");
//out(node);
paint(lct[node].ch[0]),paint(lct[node].ch[1]);
lct[node].flag=0;
}
}
int stack[10005];
void down(int node){
int top=0;
for(;node;node=lct[node].fa)stack[top++]=node;
while(top--)pushdown(stack[top]);
}
void rot(int node){
int fa=lct[node].fa;
bool dir=lct[fa].ch[1]==node;

lct[node].fa=lct[fa].fa;
lct[fa].fa=node;
lct[lct[node].ch[!dir]].fa=fa;

lct[fa].ch[dir]=lct[node].ch[!dir];
lct[node].ch[!dir]=fa;
if(lct[lct[node].fa].ch[0]==fa)lct[lct[node].fa].ch[0]=node;
else if(lct[lct[node].fa].ch[1]==fa)lct[lct[node].fa].ch[1]=node;

pushup(fa);
}
bool is_top(int node){
return lct[node].fa==0||lct[lct[node].fa].ch[1]!=node&&lct[lct[node].fa].ch[0]!=node;
}
void splay(int node){
down(node);
for(int fa;!is_top(node);rot(node)){
fa=lct[node].fa;
if(!is_top(fa))
if((lct[lct[fa].fa].ch[1]==fa)==(lct[fa].ch[1]==node))rot(fa);
else rot(node);
}
}
void discon(int node){
splay(node);
lct[node].ch[1]=0;
}
void access(int node){
//printf("---access:%d---\n",node);
for(discon(node);lct[node].fa;rot(node)){
//printf("%d\n",node);
discon(lct[node].fa);
//cout<<lct[node].fa<<".ch[1]="<<node<<endl;
lct[lct[node].fa].ch[1]=node;
}
pushup(node);
//out(21),out(22);
}
void makeroot(int node){
access(node);
paint(node);
}
void getchain(int u,int v){
makeroot(u);
access(v);
}
void link(int from,int to){
//printf("link:(%d->%d)\n",from,to);
lct[from].fa=to;
}
void cut(int from,int to){
//printf("cut:(%d->%d)\n",from,to);
lct[from].fa=lct[to].ch[0]=0;
pushup(to);
}

int deg[15][10005];

int n;
int cal(int w,int i){
return w*n+i;
}
void in(int &x){
char c=getchar();
for(;c<'0'||c>'9';c=getchar());
for(x=0;c>='0'&&c<='9';c=getchar())x=x*10+(c^'0');
}
int ptr[N*C],next[M<<1],succ[M<<1],etot=1;
void addedge(int from,int to){
next[etot]=ptr[from],ptr[from]=etot,succ[etot++]=to;
}
int q[10005];
void bfs(int node){
int h=0,t=1;
q[0]=node;
for(;h!=t;++h)
for(int i=ptr[q[h]];i;i=next[i])
if(succ[i]!=lct[q[h]].fa){
lct[succ[i]].fa=q[h];
//printf("fa(%d)=%d\n",succ[i],q[h]);
q[t++]=succ[i];
}
}
int main(){
//freopen("bzoj_2816.in","r",stdin);
//freopen("bzoj_2816.out","w",stdout);
freopen("networkzj.in","r",stdin);
freopen("networkzj.out","w",stdout);
int m,c,k;
in(n),in(m),in(c),in(k);
for(int i=1;i<=n;++i){
in(lct[i].v);
for(int j=0,k=i;j<c;++j,k+=n)lct[k].v=lct[i].v;
}
for(int i=n*c;i;--i)lct[i].max=lct[i].v;
int u,v,w;
for(int i=m;i;--i){
in(u),in(v),in(w);
addedge(cal(w,u),cal(w,v)),addedge(cal(w,v),cal(w,u));
++deg[w][u],++deg[w][v];
}
for(int i=n*c;i;--i)
if(!lct[i].fa)
bfs(i);
int opt,x,y,prew;
for(;k;--k){
//printf("----%d-----\n",k);
in(opt);
switch(opt){
case 0:
in(x),in(y);
for(int i=0;i<c;++i,x+=n){
splay(x);
lct[x].v=lct[x].max=y;
}
break;
case 1:
in(u),in(v),in(w);
for(x=u+n*(c-1),y=v+n*(c-1),prew=c-1;x>0;--prew,x-=n,y-=n){
getchain(x,y);
if(lct[x].fa==y&&!lct[x].ch[1])break;
}
//cout<<x<<" "<<y<<":"<<prew<<endl;
if(x<=0)puts("No such edge.");
else if(w==prew)puts("Success.");
else if(deg[w][u]==2||deg[w][v]==2)puts("Error 1.");
else{
getchain(cal(w,u),cal(w,v));
if(lct[cal(w,u)].fa)puts("Error 2.");
else{
puts("Success.");
cut(x,y);
--deg[prew][u],--deg[prew][v];

link(cal(w,u),cal(w,v));
++deg[w][u],++deg[w][v];
}
}
break;
case 2:
in(w),in(u),in(v);
getchain(cal(w,u),cal(w,v));
if(u==v||lct[cal(w,u)].fa)printf("%d\n",lct[cal(w,v)].max);
else puts("-1");
break;
}
}
}


总结:

①改变一个点的孩子指针前要pushdown它。

②链必须从端点开始dfs才行。

③lct中判断(u,v)是否联通,可以先access(u),再access(v),(或者直接getchain(u,v))然后看lct[u].fa,但是注意有个bug是u==v。

④lct中判断(u,v)是否存在,可以先getchain(u,v),如果存在的话,u就会是v的左儿子且u没有儿子,所以就需要看lct[u].fa!=v和lct[u].ch[1].
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: