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

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

  2. 图中不存在同色的环,同色的环指相同颜色的边构成的环。

在这个图上,你要支持以下三种操作:

  1. 修改一个节点的权值。

  2. 修改一条边的颜色。

  3. 查询由颜色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表示操作类型。

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

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

  3. k = 2为查询操作,之后三个正整数c, u和v,表示查询所有可能在节点u到节点v之间的由颜色c构成的简单路径上的节点的权值的最大值。如果不存在u和v之间不存在由颜色c构成的路径,那么输出“-1”。

 

输出格式:

 

输出文件network.out包含若干行,每行输出一个对应的信息。

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

  2. 对于修改边的颜色操作,按以下几类输出:

a) 若不存在连接节点u和节点v的边,输出“No such edge.”。

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

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

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

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

  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 题解:这题写了两个小时才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][],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]^=;
} int push_down(int x)
{
if(tag[x])
{
rev(lson);
rev(rson);
tag[x]^=;
}
} int rotate(int x)
{
int y=f[x],z=f[y],kd=ch[y][]==x,xs=ch[x][!kd];
if(not_root(y))
{
ch[z][ch[z][]==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][]==x)^(ch[z][]==y)?rotate(x):rotate(y);
}
rotate(x);
}
push_up(x);
} int access(int x)
{
for(int y=; 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 ;
f[x]=y;
return ;
} int cut(int x,int y)
{
make_root(x);
if(find_root(y)!=x||f[x]!=y||rson) return ;
f[x]=ch[y][]=;
return ;
}
int print(int x)
{
if(lson) print(lson);
printf("%d ",x);
if(rson) print(rson);
}
} tr[]; vector<pii> g[];
int n,m,c,k; int main()
{
scanf("%d%d%d%d",&n,&m,&c,&k);
for(int i=; i<=n; i++)
{
scanf("%d",&w[i]);
}
int from,to,cl;
for(int i=; 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==)
{
scanf("%d%d",&x,&y);
for(int i=; i<c; i++)
{
tr[i].splay(x);
}
w[x]=y;
}
if(kd==)
{
int flag=,tot=,tot2=,pos;
scanf("%d%d%d",&x,&y,&cc);
for(int i=; i<g[x].size(); i++)
{
if(g[x][i].first==y)
{
flag=;
pos=g[x][i].second;
}
if(g[x][i].second==cc)
{
tot++;
}
}
for(int i=; 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==)
{
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=; i<g[x].size(); i++)
{
if(g[x][i].first==y)
{
g[x][i].second=cc;
break;
}
}
for(int i=; i<g[y].size(); i++)
{
if(g[y][i].first==x)
{
g[y][i].second=cc;
break;
}
}
puts("Success.");
}
if(kd==)
{
scanf("%d%d%d",&cc,&x,&y);
tr[cc].make_root(x);
if(tr[cc].find_root(y)!=x)
{
puts("-1");
continue;
}
printf("%d\n",tr[cc].sum[y]);
}
}
}


洛谷P2173 [ZJOI2012]网络(10棵lct与瞎jb暴力)的更多相关文章

  1. 洛谷 P2173 [ZJOI2012]网络 解题报告

    P2173 [ZJOI2012]网络 题目描述 有一个无向图G,每个点有个权值,每条边有一个颜色.这个无向图满足以下两个条件: 对于任意节点连出去的边中,相同颜色的边不超过两条. 图中不存在同色的环, ...

  2. 洛谷 P1546 最短网络 Agri-Net

    题目链接 https://www.luogu.org/problemnew/show/P1546 题目背景 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当 ...

  3. 洛谷P1546 最短网络 Agri-Net(最小生成树,Kruskal)

    洛谷P1546 最短网络 Agri-Net 最小生成树模板题. 直接使用 Kruskal 求解. 复杂度为 \(O(E\log E)\) . #include<stdio.h> #incl ...

  4. 洛谷U19464 山村游历(Wander)(LCT,Splay)

    洛谷题目传送门 LCT维护子树信息常见套路详见我的总结 闲话 题目摘自WC模拟试题(by Philipsweng),原题目名Wander,"山村游历"是自己搞出来的中文名. 数据自 ...

  5. 洛谷P3348 [ZJOI2016]大森林(LCT,虚点,树上差分)

    洛谷题目传送门 思路分析 最简单粗暴的想法,肯定是大力LCT,每个树都来一遍link之类的操作啦(T飞就不说了) 考虑如何优化算法.如果没有1操作,肯定每个树都长一样.有了1操作,就来仔细分析一下对不 ...

  6. 洛谷U19464 山村游历(Wander)(LCT)

    洛谷题目传送门 LCT维护子树信息常见套路详见我的总结 闲话 题目摘自WC模拟试题(by Philipsweng),原题目名Wander,"山村游历"是自己搞出来的中文名. 数据自 ...

  7. [洛谷P2597] [ZJOI2012]灾难

    洛谷题目链接:[ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引 ...

  8. 洛谷P4332 [SHOI2014]三叉神经树(LCT,树剖,二分查找,拓扑排序)

    洛谷题目传送门 你谷无题解于是来补一发 随便百度题解,发现了不少诸如树剖\(log^3\)LCT\(log^2\)的可怕描述...... 于是来想想怎么利用题目的性质,把复杂度降下来. 首先,每个点的 ...

  9. 洛谷P3613 睡觉困难综合征(LCT,贪心)

    洛谷题目传送门 膜拜神犇出题人管理员!!膜拜yler和ZSY!! 没错yler连续教我这个蒟蒻写起床困难综合症和睡觉困难综合症%%%Orz,所以按位贪心的思路可以继承下来 这里最好还是写树剖吧,不过我 ...

随机推荐

  1. 局部加权线性回归(Locally weighted linear regression)

    首先我们来看一个线性回归的问题,在下面的例子中,我们选取不同维度的特征来对我们的数据进行拟合. 对于上面三个图像做如下解释: 选取一个特征,来拟合数据,可以看出来拟合情况并不是很好,有些数据误差还是比 ...

  2. Python小知识点(4)--模块相关

    1.模块: 定义:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能),本质就是以.py结尾的python文件(文件名:test.py,对应的模块名:test). 包:用来从逻辑上组 ...

  3. 4、数据类型二:Lists

    1.关于list的组织形式 列表数据类型(Lists)可以存储一个有序的字符串列表,常用的操作时向列表两段添加元素,或者获取列表的某一个片段.列表类型的底层实现是一个双向链表(double linke ...

  4. python学习——练习题(8)

    """ 题目:输出 9*9 乘法口诀表. """ def answer1(): """ 自己用最普通的双重循环 ...

  5. C#利用QrCode.Net生成二维码(Qr码

    http://www.cnblogs.com/Soar1991/archive/2012/03/30/2426115.html 现在网上很多应用都是用二维码来分享网址或者其它的信息.尤其在移动领域,二 ...

  6. TestNG Hello World入门示例

    https://www.yiibai.com/testng/hello-world-example.html https://www.yiibai.com/testng/ 作为一个经典的入门例子,这里 ...

  7. SpringMVC配置过程中出现的问题!

    <c:set var="ctx" value="${pageContext.request.contextPath}" />不起作用,原因是web. ...

  8. Ryu控制器学习

    Ryu 在Mininet环境下实现Ryu为控制器控制ARP报文的实验中学习了Ryu相关的知识,记录如下 官方文档:http://ryu.readthedocs.io/en/latest/getting ...

  9. Windows安装Mysql5.7.22

    1.下载Mysql,5.7版本,将zip包解压到某个安装目录下面,最好不要放C盘,选择一个容量大的磁盘.下载地址:https://dev.mysql.com/downloads/mysql/ 2.进入 ...

  10. Python常见函数用法

    1. shape()函数 在numpy模块 输入参数:类似数组(比如列表,元组)等,或是数组 返回:一个整型数字的元组,元组中的每个元素表示相应的数组每一维的长度 # shape[0]返回对象的行数, ...