题目:
题解:
写道裸题冷静一下结果因为手残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));
}
}
}