ZJOI2012网络 题解报告【LCT】
题目描述
有一个无向图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
说明

颜色0为实线的边,颜色1为虚线的边,
由颜色0构成的从节点1到节点4的路径有1 – 2 – 4,故max{v1, v2, v4} = max{ 1, 2, 4 } = 4。
将连接节点1和节点2的边修改为颜色1,修改成功,输出“Success.”
将连接节点4和节点3的边修改为颜色1,由于修改后会使得存在由颜色1构成的环( 1 – 2 – 4 – 3 – 1 ),不满足条件2,故不修改,并输出“Error 2”。
不存在颜色0构成的从节点1到节点4的边,输出“-1”。
将连接节点2和节点3的边修改为颜色1,由于修改后节点2的连出去的颜色为1的边有3条,故不满足条件1,故不修改,并输出“Error 1.”。
将节点2的权值修改为5。
由颜色1构成的从节点1到节点4的路径有 1 – 2 – 4,故max{v1, v2, v4} = max{ 1, 5, 4 } = 5。
【数据规模】
对于30%的数据:N ≤ 1000,M ≤ 10000,C ≤ 10,K ≤ 1000。
另有20%的数据:N ≤ 10000,M ≤ 100000,C = 1,K ≤ 100000。
对于100%的数据:N ≤ 10000,M ≤ 100000,C ≤ 10,K ≤ 100000。
题解
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define isr(u,c) (e[c][e[c][u].f].ch[1] == u)
#define isrt(u,c) (!e[c][u].f || (e[c][e[c][u].f].ch[0] != u && e[c][e[c][u].f].ch[1] != u))
using namespace std;
const int maxn = 10005,maxm = 100005,INF = 200000000; inline int read(){
int out = 0,flag = 1;char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = out * 10 + c - 48; c = getchar();}
return out * flag;
} int N,M,C,K,temp[maxn];
int edge[maxn][11][3]; struct node{
int w,f,ch[2],rev,Max;
node() {f = ch[0] = ch[1] = rev = 0;}
}e[11][maxn]; inline void push_up(int u,int c){
e[c][u].Max = max(e[c][u].w,max(e[c][e[c][u].ch[0]].Max,e[c][e[c][u].ch[1]].Max));
} inline void pd(int u,int c){
if (e[c][u].rev){
swap(e[c][u].ch[0],e[c][u].ch[1]);
e[c][e[c][u].ch[0]].rev ^= 1;
e[c][e[c][u].ch[1]].rev ^= 1;
e[c][u].rev = 0;
}
} inline void push_down(int u,int c){
int i = 0;
do {temp[++i] = u;} while(!isrt(u,c) && (u = e[c][u].f));
while (i) pd(temp[i--],c);
} inline int Find(int u,int c){
while (e[c][u].f) u = e[c][u].f;
return u;
} inline void spin(int u,int c){
int s = isr(u,c),fa = e[c][u].f;
e[c][u].f = e[c][fa].f;
if(!isrt(fa,c)) e[c][e[c][fa].f].ch[isr(fa,c)] = u;
e[c][fa].ch[s] = e[c][u].ch[s^1];
if(e[c][u].ch[s^1]) e[c][e[c][u].ch[s^1]].f = fa;
e[c][fa].f = u;
e[c][u].ch[s^1] = fa;
push_up(fa,c);
} inline void splay(int u,int c){
push_down(u,c);
while (!isrt(u,c)){
if(isrt(e[c][u].f,c)) spin(u,c);
else if(isr(u,c) ^ isr(e[c][u].f,c)) spin(u,c),spin(u,c);
else spin(e[c][u].f,c),spin(u,c);
}
push_up(u,c);
} inline void Access(int u,int c){
for (int v = 0; u; u = e[c][v = u].f){
splay(u,c);
e[c][u].ch[1] = v;
if (v) e[c][v].f = u;
push_up(u,c);
}
} inline void Make_root(int u,int c){
Access(u,c); splay(u,c);
e[c][u].rev ^= 1;
} inline bool Link(int u,int v,int c){
if(Find(u,c) == Find(v,c)){
printf("Error 2.\n");
return false;
}
Make_root(u,c); Access(v,c); splay(v,c);
e[c][u].f = v;
return true;
} inline void Cut(int u,int v,int c){
Make_root(u,c); Access(v,c); splay(v,c);
e[c][v].ch[0] = 0;
e[c][u].f = 0;
push_up(v,c);
} inline void Change(int u,int w){
for (int i = 0; i < C; i++){
Access(u,i); splay(u,i);
e[i][u].w = w;
push_up(u,i);
}
} inline int Query(int u,int v,int c){
if(Find(u,c) != Find(v,c)) return -1;
Make_root(u,c); Access(v,c); splay(v,c);
return e[c][v].Max;
} void init(){
for (int i = 0; i <= 10; i++) e[i][0].Max = -INF;
N = read();
M = read();
C = read();
K = read();
int u,v,w;
for (int i = 1; i <= N; i++){
w = read();
for (int j = 0; j < C; j++)
e[j][i].w = e[j][i].Max = w;
}
while (M--){
u = read();
v = read();
w = read();
Link(u,v,w);
edge[u][w][++edge[u][w][0]] = v;
edge[v][w][++edge[v][w][0]] = u;
}
} void solve(){
int k,x,y,z,c;
while (K--){
k = read();
if (k == 0){
x = read(); y = read();
Change(x,y);
}else if (k == 1){
x = read(); y = read(); z = read();
c = -1;
for (int i = 0; i < C; i++)
for (int j = 1; j <= edge[x][i][0]; j++)
if (edge[x][i][j] == y){
c = i;
if (edge[x][i][0] == 2 && j == 1) swap(edge[x][i][1],edge[x][i][2]);
if (edge[y][i][0] == 2 && edge[y][i][1] == x) swap(edge[y][i][1],edge[y][i][2]);
break;
}
if (c == -1) printf("No such edge.\n");
else if(c == z) printf("Success.\n");
else if(edge[x][z][0] == 2 || edge[y][z][0] == 2) printf("Error 1.\n");
else{
if (Link(x,y,z)){
edge[x][c][0]--;
edge[y][c][0]--;
edge[x][z][++edge[x][z][0]] = y;
edge[y][z][++edge[y][z][0]] = x;
Cut(x,y,c);
printf("Success.\n");
}
}
}else{
c = read(); x = read(); y = read();
printf("%d\n",Query(x,y,c));
}
}
} int main()
{
init();
solve();
return 0;
}
ZJOI2012网络 题解报告【LCT】的更多相关文章
- 洛谷 P2173 [ZJOI2012]网络 解题报告
P2173 [ZJOI2012]网络 题目描述 有一个无向图G,每个点有个权值,每条边有一个颜色.这个无向图满足以下两个条件: 对于任意节点连出去的边中,相同颜色的边不超过两条. 图中不存在同色的环, ...
- 洛谷P2173 [ZJOI2012]网络(10棵lct与瞎jb暴力)
有一个无向图G,每个点有个权值,每条边有一个颜色.这个无向图满足以下两个条件: 对于任意节点连出去的边中,相同颜色的边不超过两条. 图中不存在同色的环,同色的环指相同颜色的边构成的环. 在这个图上,你 ...
- BZOJ2816:[ZJOI2012]网络——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2816 https://www.luogu.org/problemnew/show/P2173 有一 ...
- 2015浙江财经大学ACM有奖周赛(一) 题解报告
2015浙江财经大学ACM有奖周赛(一) 题解报告 命题:丽丽&&黑鸡 这是命题者原话. 题目涉及的知识面比较广泛,有深度优先搜索.广度优先搜索.数学题.几何题.贪心算法.枚举.二进制 ...
- cojs 强连通图计数1-2 题解报告
OwO 题目含义都是一样的,只是数据范围扩大了 对于n<=7的问题,我们直接暴力搜索就可以了 对于n<=1000的问题,我们不难联想到<主旋律>这一道题 没错,只需要把方程改一 ...
- cojs 二分图计数问题1-3 题解报告
OwO 良心的FFT练手题,包含了所有的多项式基本运算呢 其中一部分解法参考了myy的uoj的blog 二分图计数 1: 实际是求所有图的二分图染色方案和 我们不妨枚举这个图中有多少个黑点 在n个点中 ...
- 题解报告:hdu 1398 Square Coins(母函数或dp)
Problem Description People in Silverland use square coins. Not only they have square shapes but also ...
- 题解报告:hdu 2069 Coin Change(暴力orDP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2069 Problem Description Suppose there are 5 types of ...
- 题解报告:hdu 1028 Ignatius and the Princess III(母函数or计数DP)
Problem Description "Well, it seems the first problem is too easy. I will let you know how fool ...
随机推荐
- Arduino语言
Arduino语言 Arduino语言是建立在C/C++基础上的,其实也就是基础的C语言,Arduino语言只不过把AVR单片机(微控制器)相关的一些参数设置都函数化,不用我们去了解他的底层,让我们不 ...
- EOJ3650 转机折扣(26进制,字符串)
题面 看成26进制,把较小的那个字符串加1 strcmp(s1,s2)s1和s2有大小时,不一定都是返回1或者-1.....这个地方wa了好几次没有发现 #include<bits/stdc++ ...
- Charles连接苹果及JSON乱码情况解决
1. Charles的JSON乱码情况解决: 点击Charles界面上的help—SSL proxying—install Charles Root Certificate,将证书安装到[受信任的根 ...
- Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习
Unity 2-4 UGUI Unity5.1 UI 案例学习 任务1-1:UGUI简介 什么是GUI: 游戏的开始菜单 RPG游戏的菜单栏.侧边栏和功能栏(比如背包系统.任务列表等) 设计用来控制移 ...
- 谈谈你对Java异常处理机制的理解
先谈谈我的理解:异常处理机制可以说是让我们编写的程序运行起来更加的健壮,无论是在程序调试.运行期间发生的异常情况的捕获,都提供的有效的补救动作,任何业务逻辑都会存在异常情况,这时只需要记录这些异常情况 ...
- List Leaves 树的层序遍历
3-树2 List Leaves (25 分) Given a tree, you are supposed to list all the leaves in the order of top do ...
- [leetcode]三数之和
三数之和 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复 ...
- 笔试题:C++打印队列
题目:打印队列 题目介绍:现在用打印机打印队列,已知打印任务有9个优先级(1-9),现在给出一系列任务,求输出打印顺序(任务下标,从0开始). 例: 输入:9,3,5,4,7,1 输出:0,4,2,3 ...
- We are writing to let you know we have removed your selling privileges
Hello, We are writing to let you know we have removed your selling privileges, canceled your listin ...
- python中的os.walk
原文出处:https://www.jianshu.com/p/bbad16822eab python中os.walk是一个简单易用的文件.目录遍历器,可以帮助我们高效的处理文件.目录方面的事情. 1. ...