bzoj2594
关于为什么最小花费的那条路在最小生成树上,证明见郭华阳的《RMQ与LCA问题》
t了的代码,因为有很多记录,经验和教训,所以就还是贴了出来。
现在才发现t是因为输入,一直没注意过输入输出的优化,今天算是吃一堑(qian,四声),长一智。
(不ac的代码也舍不得扔,另外,有没有什么编译器是可以隐藏注释的?需要的时候,才看,不需要的时候就藏起来,有没有?有没有?有没有?重要的事情说三遍!!!想吃薯片!!!)
2015.9.11:
要注意输入输出。
t了的代码:
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; #define N 100010 #define M 1000010 struct node{ node *fa; node *ch[2]; int rev; int val; int valnum; int maxval; int maxnum; int from; int to; void init(int tempval,int tempvalnum,int tempfrom,int tempto){ ch[0]=ch[1]=fa=NULL; rev=0; val=tempval; valnum=tempvalnum; maxval=val; maxnum=valnum; from=tempfrom; to=tempto; } bool isroot(){ return fa==NULL||(fa->ch[0]!=this&&fa->ch[1]!=this); } void fswitch(){ rev^=1; swap(ch[0],ch[1]); return; } void push_down(){ if(rev){ if(ch[0]){ ch[0]->fswitch(); } if(ch[1]){ ch[1]->fswitch(); } rev=0; } return; } void go(){ if(!isroot()){ fa->go();//调错:这里是go,不是isroot。写代码是即使写过很多遍,也要想着意义写,否则!!!!还有如果不ac的时候,要想办法锁定出错范围,而不是没有逻辑的测试 } push_down(); return; } int dir(){ return fa->ch[1]==this?1:0; } void setedge(int d,node *another){ ch[d]=another; if(another){ another->fa=this; } return; } void push_up(){ maxnum=valnum; maxval=val; if(ch[0]&&ch[0]->maxnum>maxnum){ maxnum=ch[0]->maxnum; maxval=ch[0]->maxval; } if(ch[1]&&ch[1]->maxnum>maxnum){ maxnum=ch[1]->maxnum; maxval=ch[1]->maxval; } return; } void rot(){ int d=dir(); node *tempfafa=fa->fa; if(!(fa->isroot())){ tempfafa->ch[fa->dir()]=this; } fa->setedge(d,ch[!d]); setedge(!d,fa); fa=tempfafa; ch[!d]->push_up(); return; } void splay(){ go(); while(!isroot()){ if(!(fa->isroot())){ dir()==fa->dir()?fa->rot():rot(); } rot(); } push_up(); return; } void access(){ for(node *p=this,*q=NULL;p!=NULL;q=p,p=p->fa){ p->splay(); p->setedge(1,q); p->push_up(); } splay(); } void make_root(){ access(); fswitch(); return; } node *find_root(){ node *temp=this; while(temp->fa){ temp=temp->fa; } return temp; } bool islink(node *another){ return find_root()==another->find_root()?true:false; } void cut(node *another){ //printf("hahaha\n");//调错:cut运行了两次,第二次时出现了问题,在将2,3这条边和3切开时,出的错。 another->make_root(); access(); /*if(islink(another)){调错:if中的printf同时输出 printf("wo shi da hao ren\n"); } if(!islink(another)){ printf("wo bu shi da hao ren\n"); } if(!ch[0]&&!ch[1]){//调错:断开2,3这条边时,access后,左右自孩子均没点 printf("%d\n",val); }*/ ch[0]->fa=NULL; ch[0]=NULL; push_up(); return; } void link(node *another){ another->make_root(); another->fa=this; return; } int query(node *another){ another->make_root(); access(); return maxval; } }; struct edge{ int minfrom; int maxto; int wedge; bool isexist; }; struct op{ int type; int a,b; int wedge; int ans; }; node *tree[2*N],pool[2*N]; edge edgearray[M]; op oparray[N]; int cou; bool cmp(edge a,edge b){ if(a.minfrom==b.minfrom){ return a.maxto<b.maxto; } else{ return a.minfrom<b.minfrom; } } int fmark(op tempop,int m){ int l=0; int r=m-1; int middle=(l+r)>>1; if(tempop.a>tempop.b){ swap(tempop.a,tempop.b); } while(!(tempop.a==edgearray[middle].minfrom&&tempop.b==edgearray[middle].maxto)){ if(tempop.a>edgearray[middle].minfrom){ l=middle+1; } else if(tempop.a<edgearray[middle].minfrom){ r=middle-1; } else{ if(tempop.b>edgearray[middle].maxto){ l=middle+1; } else{ r=middle-1; } } middle=(l+r)>>1; } edgearray[middle].isexist=false; return edgearray[middle].wedge; } void addedge(int x,int y,int w){ if(tree[x]->islink(tree[y])){ //printf("%d %d\n",x,y); int tempid=tree[x]->query(tree[y]);//到此为止,边的连接什么的都是正确的 //printf("%d %d %d %d\n",tempid,tree[tempid]->from,tree[tempid]->to,tree[tempid]->valnum); if(tree[tempid]->valnum>w){ //printf("cut: %d %d\n",tree[tempid]->from,tree[tempid]->to); //此时都连着 //调错:经过这一步,因为错误,就都断开了,但是如果将from和to兑换后,就对了 //printf("wo shi da hao ren\n"); tree[tempid]->cut(tree[tree[tempid]->from]); //tree[tree[tempid]->from]->make_root(); /*tree[tree[tempid]->from]->access();//目前为止边的连接是正确的; tree[tree[tempid]->from]->fswitch(); tree[3]->go(); for(int i=1;i<=cou;i++){ //tree[i]->go(); if(tree[i]->rev){ printf("rev存在 "); } printf("%d %d %d ",i,tree[i]->from,tree[i]->to); if(tree[i]->fa){ printf("fa:%d ",tree[i]->fa->val); } if(tree[i]->ch[0]){ printf("ch[0]:%d ",tree[i]->ch[0]->val); } if(tree[i]->ch[1]){ printf("ch[1]:%d ",tree[i]->ch[1]->val); } printf("\n"); } tree[tempid]->access(); tree[tempid]->ch[0]->fa=NULL; tree[tempid]->ch[0]=NULL; tree[tempid]->push_up(); if(tree[tempid]->islink(tree[tree[tempid]->from])){ printf("%d和%d连着\n",tempid,tree[tempid]->from); } if(tree[tempid]->islink(tree[tree[tempid]->to])){ printf("%d和%d连着\n",tempid,tree[tempid]->to); }*/ tree[tempid]->cut(tree[tree[tempid]->to]); //printf("wo shi da hao ren\n");//上一步出现了错误 tree[tempid]->init(tree[tempid]->val,w,x,y); //printf("link: %d %d\n",x,y); tree[tempid]->link(tree[x]); tree[tempid]->link(tree[y]); /*if(tree[tempid]->islink(tree[x])){ printf("%d,%d这条边已连上了%d\n",x,y,x); } if(tree[tempid]->islink(tree[y])){ printf("%d,%d这条边已连上了%d\n",x,y,y); }*/ } } else{ //printf("wo shi da hao ren"); tree[++cou]=&(pool[cou]); tree[cou]->init(cou,w,x,y); //printf("link: %d %d\n",x,y); tree[cou]->link(tree[x]); tree[cou]->link(tree[y]); /*if(tree[cou]->islink(tree[x])){ printf("%d,%d这条边已连上了%d\n",x,y,x); } if(tree[cou]->islink(tree[y])){ printf("%d,%d这条边已连上了%d\n",x,y,y); }*/ } return; } int main(){ int n,m,q; int a,b,c; int w; scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=n;i++){ tree[i]=&(pool[i]); tree[i]->init(i,-1,-1,-1); } for(int i=0;i<m;i++){ scanf("%d%d%d",&a,&b,&edgearray[i].wedge); if(a>b){ edgearray[i].minfrom=b; edgearray[i].maxto=a; } else{ edgearray[i].minfrom=a; edgearray[i].maxto=b; } edgearray[i].isexist=true; } sort(edgearray,edgearray+m,cmp); cou=n; for(int i=0;i<q;i++){ scanf("%d%d%d",&oparray[i].type,&oparray[i].a,&oparray[i].b); if(oparray[i].type==2){ oparray[i].wedge=fmark(oparray[i],m); } } for(int i=0;i<m;i++){ if(edgearray[i].isexist){ addedge(edgearray[i].minfrom,edgearray[i].maxto,edgearray[i].wedge); } } //printf("wo shi da hao ren"); for(int i=q-1;i>=0;i--){ if(oparray[i].type==1){ oparray[i].ans=tree[tree[oparray[i].a]->query(tree[oparray[i].b])]->valnum; //printf("%d\n",oparray[i].ans); } else{ /*if(tree[6]->islink(tree[2])){//调错:至今为止,这两个if中的printf都会输出 printf("wo shi da hao ren\n"); } if(tree[6]->islink(tree[3])){ printf("wo bu shi da huai dan\n"); } for(int i=1;i<=cou;i++){ printf("%d %d %d ",i,tree[i]->from,tree[i]->to); if(tree[i]->fa){ printf("fa:%d ",tree[i]->fa->val); } if(tree[i]->ch[0]){ printf("ch[0]:%d ",tree[i]->ch[0]->val); } if(tree[i]->ch[1]){ printf("ch[1]:%d ",tree[i]->ch[1]->val); } printf("\n"); }*/ addedge(oparray[i].a,oparray[i].b,oparray[i].wedge); } } for(int i=0;i<q;i++){ if(oparray[i].type==1){ printf("%d\n",oparray[i].ans); } } return 0; }ac了的代码
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; #define N 100010 #define M 1000010 struct node{ node *fa; node *ch[2]; int rev; int val; int valnum; int maxval; int maxnum; int from; int to; void init(int tempval,int tempvalnum,int tempfrom,int tempto){ ch[0]=ch[1]=fa=NULL; rev=0; val=tempval; valnum=tempvalnum; maxval=val; maxnum=valnum; from=tempfrom; to=tempto; } bool isroot(){ return fa==NULL||(fa->ch[0]!=this&&fa->ch[1]!=this); } void fswitch(){ rev^=1; swap(ch[0],ch[1]); return; } void push_down(){ if(rev){ if(ch[0]){ ch[0]->fswitch(); } if(ch[1]){ ch[1]->fswitch(); } rev=0; } return; } void go(){ if(!isroot()){ fa->go();//调错:这里是go,不是isroot。写代码是即使写过很多遍,也要想着意义写,否则!!!!还有如果不ac的时候,要想办法锁定出错范围,而不是没有逻辑的测试 } push_down(); return; } int dir(){ return fa->ch[1]==this?1:0; } void setedge(int d,node *another){ ch[d]=another; if(another){ another->fa=this; } return; } void push_up(){ maxnum=valnum; maxval=val; if(ch[0]&&ch[0]->maxnum>maxnum){ maxnum=ch[0]->maxnum; maxval=ch[0]->maxval; } if(ch[1]&&ch[1]->maxnum>maxnum){ maxnum=ch[1]->maxnum; maxval=ch[1]->maxval; } return; } void rot(){ int d=dir(); node *tempfafa=fa->fa; if(!(fa->isroot())){ tempfafa->ch[fa->dir()]=this; } fa->setedge(d,ch[!d]); setedge(!d,fa); fa=tempfafa; ch[!d]->push_up(); return; } void splay(){ go(); while(!isroot()){ if(!(fa->isroot())){ dir()==fa->dir()?fa->rot():rot(); } rot(); } push_up(); return; } void access(){ for(node *p=this,*q=NULL;p!=NULL;q=p,p=p->fa){ p->splay(); p->setedge(1,q); p->push_up(); } splay(); } void make_root(){ access(); fswitch(); return; } node *find_root(){ node *temp=this; while(temp->fa){ temp=temp->fa; } return temp; } bool islink(node *another){ return find_root()==another->find_root()?true:false; } void cut(node *another){ another->make_root(); access(); ch[0]->fa=NULL; ch[0]=NULL; push_up(); return; } void link(node *another){ another->make_root(); another->fa=this; return; } int query(node *another){ another->make_root(); access(); return maxval; } }; struct edge{ int minfrom; int maxto; int wedge; bool isexist; }; struct op{ int type; int a,b; int wedge; int ans; }; node *tree[2*N],pool[2*N]; edge edgearray[M]; op oparray[N]; int cou; bool cmp(edge a,edge b){ if(a.minfrom==b.minfrom){ return a.maxto<b.maxto; } else{ return a.minfrom<b.minfrom; } } int fmark(op tempop,int m){ int l=0; int r=m-1; int middle=(l+r)>>1; if(tempop.a>tempop.b){ swap(tempop.a,tempop.b); } while(!(tempop.a==edgearray[middle].minfrom&&tempop.b==edgearray[middle].maxto)){ if(tempop.a>edgearray[middle].minfrom){ l=middle+1; } else if(tempop.a<edgearray[middle].minfrom){ r=middle-1; } else{ if(tempop.b>edgearray[middle].maxto){ l=middle+1; } else{ r=middle-1; } } middle=(l+r)>>1; } edgearray[middle].isexist=false; return edgearray[middle].wedge; } void addedge(int x,int y,int w){ if(tree[x]->islink(tree[y])){ int tempid=tree[x]->query(tree[y]); if(tree[tempid]->valnum>w){ tree[tempid]->cut(tree[tree[tempid]->from]); tree[tempid]->cut(tree[tree[tempid]->to]); tree[tempid]->init(tree[tempid]->val,w,x,y); tree[tempid]->link(tree[x]); tree[tempid]->link(tree[y]); } } else{ tree[++cou]=&(pool[cou]); tree[cou]->init(cou,w,x,y); tree[cou]->link(tree[x]); tree[cou]->link(tree[y]); } return; } int getint(){ int ans=0; char tempc; for(;tempc=getchar(),tempc<'0'||tempc>'9';); ans=tempc-'0'; for(;tempc=getchar(),tempc>='0'&&tempc<='9';){ ans=ans*10+tempc-'0'; } return ans; } int main(){ int n,m,q; int a,b,c; int w; n=getint(); m=getint(); q=getint(); //scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=n;i++){ tree[i]=&(pool[i]); tree[i]->init(i,-1,-1,-1); } for(int i=0;i<m;i++){ a=getint(); b=getint(); edgearray[i].wedge=getint(); //scanf("%d%d%d",&a,&b,&edgearray[i].wedge); if(a>b){ edgearray[i].minfrom=b; edgearray[i].maxto=a; } else{ edgearray[i].minfrom=a; edgearray[i].maxto=b; } edgearray[i].isexist=true; } sort(edgearray,edgearray+m,cmp); cou=n; for(int i=0;i<q;i++){ oparray[i].type=getint(); oparray[i].a=getint(); oparray[i].b=getint(); //scanf("%d%d%d",&oparray[i].type,&oparray[i].a,&oparray[i].b); if(oparray[i].type==2){ oparray[i].wedge=fmark(oparray[i],m); } } for(int i=0;i<m;i++){ if(edgearray[i].isexist){ addedge(edgearray[i].minfrom,edgearray[i].maxto,edgearray[i].wedge); } } for(int i=q-1;i>=0;i--){ if(oparray[i].type==1){ oparray[i].ans=tree[tree[oparray[i].a]->query(tree[oparray[i].b])]->valnum; } else{ addedge(oparray[i].a,oparray[i].b,oparray[i].wedge); } } for(int i=0;i<q;i++){ if(oparray[i].type==1){ printf("%d\n",oparray[i].ans); } } return 0; }