有一个无向图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.”。
- 对于查询操作,直接输出一个整数。
输入输出样例
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
4
Success.
Error 2.
-1
Error 1.
5
题解:这题写了两个小时才A掉,估计没人比我更菜了
这题的语文要求还有点小高,我们一个一个来分析
首先看到颜色个数很少,而且颜色会变,不难想到对每种颜色搞一颗lct
那么第一个操作权值修改就是将每颗lct里的x rotate到当前splay的根,接着更新权值。
第二个操作比较繁琐
首先是没边的情况,因为题目保证了每个点相同颜色的边不超过两条,所以每个点最多有20条边,这样可以暴力遍历每一条边,查找是不是存在x到y的边。
接着是边数超过两条的情况,很显然还是暴力搜每一条边,如果x和y两点有一点已经连接了两个该颜色,那就GG了
接着是是否已经联通的问题,显然make_root然后find_root一下就可以了
最后就是把原来颜色的lct里cut一下,现在lct里link一下就行了。
第三个操作中规中矩
就是splay里push_up一下,把x splay到根,接着输出答案就行了。
最大的坑点——可能x到y的边被更新成原来的颜色,这样子操作二的第二种情况就会出锅,所以要优先处理一下,
代码如下:
#include<map> #include<set> #include<queue> #include<cmath> #include<cstdio> #include<string> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define N 10010 #define mp make_pair #define lson ch[x][0] #define rson ch[x][1] #define pii pair<int,int> using namespace std; int w[N]; struct lct { int sum[N],f[N],ch[N][2],tag[N]; int not_root(int now) { int x=f[now]; return lson==now||rson==now; } int push_up(int x) { sum[x]=max(max(sum[lson],sum[rson]),w[x]); } int rev(int x) { swap(lson,rson); tag[x]^=1; } int push_down(int x) { if(tag[x]) { rev(lson); rev(rson); tag[x]^=1; } } int rotate(int x) { int y=f[x],z=f[y],kd=ch[y][1]==x,xs=ch[x][!kd]; if(not_root(y)) { ch[z][ch[z][1]==y]=x; } ch[x][!kd]=y; ch[y][kd]=xs; if(xs) f[xs]=y; f[y]=x; f[x]=z; push_up(y); } int push_all(int x) { if(not_root(x)) { push_all(f[x]); } push_down(x); } int splay(int x) { int y,z; push_all(x); while(not_root(x)) { y=f[x],z=f[y]; if(not_root(y)) { (ch[y][0]==x)^(ch[z][0]==y)?rotate(x):rotate(y); } rotate(x); } push_up(x); } int access(int x) { for(int y=0; x; y=x,x=f[x]) { splay(x); rson=y; push_up(x); } } int make_root(int x) { access(x); splay(x); rev(x); } int split(int x,int y) { make_root(x); access(y); splay(y); } int find_root(int x) { access(x); splay(x); while(lson) { push_down(x); x=lson; } return x; } int link(int x,int y) { make_root(x); if(find_root(y)==x) return 0; f[x]=y; return 1; } int cut(int x,int y) { make_root(x); if(find_root(y)!=x||f[x]!=y||rson) return 0; f[x]=ch[y][0]=0; return 1; } int print(int x) { if(lson) print(lson); printf("%d ",x); if(rson) print(rson); } } tr[11]; vector<pii> g[10010]; int n,m,c,k; int main() { scanf("%d%d%d%d",&n,&m,&c,&k); for(int i=1; i<=n; i++) { scanf("%d",&w[i]); } int from,to,cl; for(int i=1; i<=m; i++) { scanf("%d%d%d",&from,&to,&cl); tr[cl].link(from,to); g[from].push_back(mp(to,cl)); g[to].push_back(mp(from,cl)); } while(k--) { int kd,x,y,cc; scanf("%d",&kd); if(kd==0) { scanf("%d%d",&x,&y); for(int i=0; i<c; i++) { tr[i].splay(x); } w[x]=y; } if(kd==1) { int flag=1,tot=0,tot2=0,pos; scanf("%d%d%d",&x,&y,&cc); for(int i=0; i<g[x].size(); i++) { if(g[x][i].first==y) { flag=0; pos=g[x][i].second; } if(g[x][i].second==cc) { tot++; } } for(int i=0; i<g[y].size(); i++) { if(g[y][i].second==cc) { tot2++; } } tot=max(tot2,tot); if(flag) { puts("No such edge."); continue; } if(pos==cc) { puts("Success."); continue; } if(tot==2) { puts("Error 1."); continue; } tr[cc].make_root(x); if(tr[cc].find_root(y)==x) { puts("Error 2."); continue; } tr[pos].cut(x,y); tr[cc].link(x,y); for(int i=0; i<g[x].size(); i++) { if(g[x][i].first==y) { g[x][i].second=cc; break; } } for(int i=0; i<g[y].size(); i++) { if(g[y][i].first==x) { g[y][i].second=cc; break; } } puts("Success."); } if(kd==2) { scanf("%d%d%d",&cc,&x,&y); tr[cc].make_root(x); if(tr[cc].find_root(y)!=x) { puts("-1"); continue; } printf("%d ",tr[cc].sum[y]); } } }