【BZOJ2816】【ZJOI2012】网络(Link-Cut Tree)

来源:互联网 发布:手机版淘宝店铺装修 编辑:程序博客网 时间:2024/06/14 08:39

题面

题目描述

有一个无向图G,每个点有个权值,每条边有一个颜色。这个无向图满足以下两个条件:

对于任意节点连出去的边中,相同颜色的边不超过两条。

图中不存在同色的环,同色的环指相同颜色的边构成的环。
在这个图上,你要支持以下三种操作:

修改一个节点的权值。

修改一条边的颜色。

查询由颜色c的边构成的图中,所有可能在节点u到节点v之间的简单路径上的节点的权值的最大值。

输入输出格式

输入格式:
输入文件network.in的第一行包含四个正整数N, M, C, K,其中N为节点个数,M为边数,C为边的颜色数,K为操作数。

接下来N行,每行一个正整数vi,为节点i的权值。

之后M行,每行三个正整数u, v, w,为一条连接节点u和节点v的边,颜色为w。满足1 ≤ u, v ≤ N,0 ≤ w < C,保证u ≠ v,且任意两个节点之间最多存在一条边(无论颜色)。

最后K行,每行表示一个操作。每行的第一个整数k表示操作类型。

k = 0为修改节点权值操作,之后两个正整数x和y,表示将节点x的权值vx修改为y。

k = 1为修改边的颜色操作,之后三个正整数u, v和w,表示将连接节点u和节点v的边的颜色修改为颜色w。满足0 ≤ w < C。

k = 2为查询操作,之后三个正整数c, u和v,表示查询所有可能在节点u到节点v之间的由颜色c构成的简单路径上的节点的权值的最大值。如果不存在u和v之间不存在由颜色c构成的路径,那么输出“-1”。
输出格式:
输出文件network.out包含若干行,每行输出一个对应的信息。

对于修改节点权值操作,不需要输出信息。

对于修改边的颜色操作,按以下几类输出:
a) 若不存在连接节点u和节点v的边,输出“No such edge.”。

b) 若修改后不满足条件1,不修改边的颜色,并输出“Error 1.”。

c) 若修改后不满足条件2,不修改边的颜色,并输出“Error 2.”。

d) 其他情况,成功修改边的颜色,并输出“Success.”。

输出满足条件的第一条信息即可,即若同时满足b和c,则只需要输出“Error 1.”。

对于查询操作,直接输出一个整数。

输入输出样例

输入样例#1:
4 5 2 7
1
2
3
4
1 2 0
1 3 1
2 3 0
2 4 1
3 4 0
2 0 1 4
1 1 2 1
1 4 3 1
2 0 1 4
1 2 3 1
0 2 5
2 1 1 4
输出样例#1:
4
Success.
Error 2.
-1
Error 1.
5

题解

考虑C<=10
那么, 暴力维护C棵树即可
直接LCT维护即可
细节真的是有点多。。。
这道题目慢慢做。。。

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#include<set>#include<map>#include<vector>#include<queue>using namespace std;#define MAX 11000#define fat t[x].ff#define lson t[x].ch[0]#define rson t[x].ch[1]inline int read(){    int x=0,t=1;char ch=getchar();    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();    if(ch=='-')t=-1,ch=getchar();    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();    return x*t;}int S[MAX],top;struct N{int u,v;};int n,m,C,K,val[MAX];int color[MAX][11];bool operator<(N a,N b){    if(a.u!=b.u)return a.u<b.u;    return a.v<b.v;}map<N,int> MM;struct Node{    int ch[2],ff;    int mm,val,rev; };struct LCT{    struct Node t[MAX];    void pushup(int x){t[x].mm=max(t[lson].mm,t[rson].mm);t[x].mm=max(t[x].mm,t[x].val);}    bool isroot(int x){return t[fat].ch[0]!=x&&t[fat].ch[1]!=x;}    void pushdown(int x)    {        if(!t[x].rev)return;        swap(lson,rson);        t[lson].rev^=1;t[rson].rev^=1;        t[x].rev^=1;    }    void rotate(int x)    {        int y=t[x].ff,z=t[y].ff;        int k=t[y].ch[1]==x;        if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;        t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;        t[x].ch[k^1]=y;t[y].ff=x;           pushup(y);pushup(x);        }    void Splay(int x)    {        S[top=1]=x;        for(int i=x;!isroot(i);i=t[i].ff)S[++top]=t[i].ff;        while(top)pushdown(S[top--]);        while(!isroot(x))        {            int y=t[x].ff,z=t[y].ff;            if(!isroot(y))                (t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);            rotate(x);        }    }    void access(int x){for(int y=0;x;y=x,x=t[x].ff)Splay(x),t[x].ch[1]=y,pushup(x);}    void makeroot(int x){access(x);Splay(x);t[x].rev^=1;}    void split(int x,int y){makeroot(x);access(y);Splay(y);}    void cut(int x,int y){split(x,y);t[y].ch[0]=t[x].ff=0;}    void link(int x,int y){makeroot(x);t[x].ff=y;}    int findroot(int x){access(x);Splay(x);while(lson)x=lson;return x;}}LCT[11];int main(){    n=read();m=read();C=read();K=read();    for(int i=1;i<=n;++i)val[i]=read();    for(int i=1;i<=n;++i)        for(int j=1;j<=C;++j)            LCT[j].t[i].val=val[i];    for(int i=1,u,v,w;i<=m;++i)    {        u=read(),v=read(),w=read()+1;        MM[(N){u,v}]=w;        MM[(N){v,u}]=w;        color[u][w]++;color[v][w]++;        LCT[w].link(u,v);    }    while(K--)    {        int opt=read();        if(opt==0)        {            int x=read();val[x]=read();            for(int i=1;i<=C;++i)            {                LCT[i].access(x);                LCT[i].Splay(x);                LCT[i].t[x].val=val[x];            }        }        else if(opt==1)        {            int u=read(),v=read(),w=read()+1;            int G=MM[(N){u,v}];            if(!G){puts("No such edge.");continue;}            if(G==w){puts("Success.");continue;}            if(color[u][w]>1||color[v][w]>1){puts("Error 1.");continue;}            if(LCT[w].findroot(u)==LCT[w].findroot(v)){puts("Error 2.");continue;}            color[u][w]++;color[v][w]++;            color[u][G]--;color[v][G]--;            MM[(N){u,v}]=w;MM[(N){v,u}]=w;            LCT[G].cut(u,v);            LCT[w].link(u,v);            puts("Success.");        }        else        {            int w=read()+1,u=read(),v=read();            if(LCT[w].findroot(u)!=LCT[w].findroot(v)){puts("-1");continue;}            LCT[w].split(u,v);            printf("%d\n",LCT[w].t[v].mm);        }    }    return 0;}
原创粉丝点击