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;
}

浙公网安备 33010602011771号