[BZOJ3651]网络通信(LCT)

题目描述

传送门

题解

板子题= =(有一点点变化而已)
给每一个公司建一个树= =
也就是所有的东东都再加一维而已= =
怎么判“任何公司不能控制连接同一个站点的两条以上的电缆”这个条件呢?
记一下每个点的度即可(煞笔吧
注意这个度也是每个公司一个哦

其他的没有什么变化了吧
判边用map

代码

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int max_n=8005;
const int max_c=105;

struct hp{
    bool flag;
    int y,x;
};
int n,m,c,t,x,y,z;
int ch[max_c][max_n][2],f[max_c][max_n],reverse[max_c][max_n];
int sum[max_c][max_n];
int strack[max_n];

inline int get(int x,int con){
    return ch[con][ f[con][x] ][1]==x;
}

inline int Is_Root(int x,int con){
    return ch[con][ f[con][x] ][0]!=x&&ch[con][ f[con][x] ][1]!=x;
}

/* inline void update(int x,int con){ } */

inline void pushdown(int x,int con){
    if (x&&reverse[con][x]){
        swap(ch[con][x][0],ch[con][x][1]);
        if (ch[con][x][0]) reverse[con][ ch[con][x][0] ]^=1;
        if (ch[con][x][1]) reverse[con][ ch[con][x][1] ]^=1;
        reverse[con][x]=0;
    }
}

inline void rotate(int x,int con){
    int old=f[con][x],oldf=f[con][old],which=get(x,con);

    if (!Is_Root(old,con))
      ch[con][oldf][ ch[con][oldf][1]==old ]=x;
    f[con][x]=oldf;

    ch[con][old][which]=ch[con][x][which^1];
    f[con][ ch[con][old][which] ]=old;

    ch[con][x][which^1]=old;
    f[con][old]=x;

// update(old,con);
// update(x,con);
}

inline void splay(int x,int con){
    int temp=0;
    strack[++temp]=x;
    for (int i=x; !Is_Root(i,con); i=f[con][i])
      strack[++temp]=f[con][i];
    for (int i=temp;i>=1;--i)
      pushdown(strack[i],con);

    for (int fa; !Is_Root(x,con); rotate(x,con))
      if (!Is_Root(fa=f[con][x],con))
        rotate( (get(x,con)==get(fa,con)) ?fa:x ,con);
}

inline void Access(int x,int con){
    int t=0;
    for (; x; t=x,x=f[con][x]){
        splay(x,con);
        ch[con][x][1]=t;
// update(x,con);
    }
}

inline void Reverse(int x,int con){
    Access(x,con);
    splay(x,con);
    reverse[con][x]^=1;
}

inline void Link(int x,int y,int con){
    Reverse(x,con);
    f[con][x]=y;
    splay(x,con);
    sum[con][x]++;
    sum[con][y]++;
}

inline hp Cut(int x,int y,int con){
    hp ans;

    Reverse(x,con);
    Access(y,con);
    splay(y,con);
    if (ch[con][y][0]==x)
      return ans=(hp){true,y,x};
    else return ans=(hp){false,0,0};
}

inline int Find(int x,int con){
    Access(x,con);
    splay(x,con);
    while (ch[con][x][0])
      x=ch[con][x][0];
    return x;
}

int main(){
    scanf("%d%d%d%d",&n,&m,&c,&t);
    for (int i=1;i<=m;++i){
        scanf("%d%d%d",&x,&y,&z);
        Link(x,y,z);
    }
    for (int i=1;i<=t;++i){
        scanf("%d%d%d",&x,&y,&z);

        hp pd;
        pd=Cut(x,y,z);
        if (pd.flag){
            printf("Already owned.\n");
            continue;
        }

        for (int j=1;j<=c;++j)
          if (j!=z){
            pd=Cut(x,y,j);
            if (pd.flag){

                if (sum[z][x]==2||sum[z][y]==2){
                    printf("Forbidden: monopoly.\n");
                    break;
                }

                if (Find(x,z)==Find(y,z)){
                    printf("Forbidden: redundant.\n");
                    break;
                }

                printf("Sold.\n");

                ch[j][pd.y][0]=f[j][pd.x]=0;
                sum[j][y]--;
                sum[j][x]--;

                Link(x,y,z);
                break;
            }
          }
        if (!pd.flag){
            printf("No such cable.\n");
            continue;
        }
    }
}

总结

map大法好!

你可能感兴趣的:(bzoj,LCT)