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


posted @ 2015-09-03 17:11  buzhidaohahaha  阅读(156)  评论(0编辑  收藏  举报