[BZOJ2816][ZJOI2012]网络(LCT)

11 篇文章 0 订阅

题目:

我是超链接

题解:

写道裸题冷静一下结果因为手残WA了几次,对于每个c维护一棵LCT,判断是否有边的方式是用map,然后记录一下每一个点在每一种颜色的图中的度

代码:

#include <map>
#include <cstdio>
#include <iostream>
using namespace std;
const int N=10005;
struct line{
    int x,y;
    line(int X,int Y){x=X;y=Y;}
};
map<line,int>col;
bool operator <(const line a,const line b){return a.x<b.x || (a.x==b.x && a.y<b.y);}
int ch[15][N][2],f[15][N],maxx[15][N],v[15][N],delta[15][N],stack[N],du[15][N];
bool isroot(int w,int x){return ch[w][f[w][x]][0]!=x && ch[w][f[w][x]][1]!=x;}
int get(int w,int x){return ch[w][f[w][x]][1]==x;}
void updata(int w,int now)
{
    maxx[w][now]=v[w][now];
    if (ch[w][now][0]) maxx[w][now]=max(maxx[w][now],maxx[w][ch[w][now][0]]);
    if (ch[w][now][1]) maxx[w][now]=max(maxx[w][now],maxx[w][ch[w][now][1]]);
}
void pushdown(int w,int now)
{
    if (delta[w][now])
    {
        delta[w][ch[w][now][0]]^=1; delta[w][ch[w][now][1]]^=1;
        swap(ch[w][now][0],ch[w][now][1]);
        delta[w][now]=0;
    }
}
void rotate(int w,int x)
{
    int old=f[w][x],oldf=f[w][old],which=get(w,x);
    f[w][x]=oldf; if (!isroot(w,old)) ch[w][oldf][get(w,old)]=x;
    ch[w][old][which]=ch[w][x][which^1]; f[w][ch[w][x][which^1]]=old;
    ch[w][x][which^1]=old; f[w][old]=x;
    updata(w,old); updata(w,x);
}
void splay(int w,int x)
{
    int top=0,i;
    for (i=x;!isroot(w,i);i=f[w][i]) stack[++top]=i;
    stack[++top]=i;
    for (int i=top;i>=1;i--) pushdown(w,stack[i]);
    for (;!isroot(w,x);rotate(w,x))
      if (!isroot(w,f[w][x])) rotate(w,get(w,x)==get(w,f[w][x])?f[w][x]:x);
}
void access(int w,int x)
{
    int t=0;
    for (;x;t=x,x=f[w][x])
    {
        splay(w,x);
        ch[w][x][1]=t;
        updata(w,x);
    }
}
void reverse(int w,int x)
{
    access(w,x);
    splay(w,x);
    delta[w][x]^=1;
}
int find(int w,int x)
{
    while (ch[w][x][0]) x=ch[w][x][0];
    return x;
}
bool connect(int w,int x,int y)
{
    access(w,x); splay(w,x);
    int fa1=find(w,x);
    access(w,y); splay(w,y);
    int fa2=find(w,y);
    if (fa1==fa2) return 1;return 0;
}
int Link(int w,int x,int y)
{
    if (connect(w,x,y)) return 0;
    reverse(w,x);
    f[w][x]=y; splay(w,x);
    return 1;
}
int Cut(int w,int x,int y)
{
    if (!connect(w,x,y)) return 0;
    reverse(w,x); access(w,y);
    splay(w,y); ch[w][y][0]=f[w][x]=0;
    return 1;
}
int qurry(int w,int x,int y)
{
    reverse(w,x); access(w,y);
    splay(w,y); return maxx[w][y];
}
int main()
{
    int x,y,w,id,n,m,c,k;
    scanf("%d%d%d%d",&n,&m,&c,&k);
    for (int i=1;i<=n;i++) 
    {
        scanf("%d",&x);
        for (int j=0;j<c;j++) v[j][i]=x;
    }
    for (int i=1;i<=m;i++) 
    {
        scanf("%d%d%d",&x,&y,&w); if (x>y) swap(x,y);
        Link(w,x,y); 
        col[line(x,y)]=w+1;
        du[w][x]++; du[w][y]++;
    }
    for (int i=1;i<=k;i++)
    {
        scanf("%d",&id);
        if (id==0) 
        {
            scanf("%d%d",&x,&y);
            for (int j=0;j<c;j++) v[j][x]=y,splay(j,x);
        }else if (id==1)
        {
            scanf("%d%d%d",&x,&y,&w);if (x>y) swap(x,y);
            if (!col[line(x,y)]) {printf("No such edge.\n");continue;}
            if (col[line(x,y)]==w+1) {printf("Success.\n");continue;}
            if (du[w][x]==2 || du[w][y]==2) {printf("Error 1.\n");continue;}
            if (!Link(w,x,y)) {printf("Error 2.\n");continue;}
            Cut(col[line(x,y)]-1,x,y); du[w][x]++; du[w][y]++; du[col[line(x,y)]-1][x]--; du[col[line(x,y)]-1][y]--;
            col[line(x,y)]=w+1;printf("Success.\n");
        }else
        {
            scanf("%d%d%d",&w,&x,&y);
            if (!connect(w,x,y)) printf("-1\n");else printf("%d\n",qurry(w,x,y));
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值