描述

有一个无向图,有n个点,m1条第一类边和m2条第二类边。第一类边有边权,第二类边无边权。请为第二类的每条边定义一个边权,使得第二类边可能全部出现在该无向图的最小生成树上,同时要求第二类边的边权总和尽可能大。
注:第二类边不会形成环

输入

第一行三个数n,m2,m1

接下来m2行,每行两个数,描述一条第二类边,分别表示两个端点接下来m1行,每行三个数,描述一条第一类边,分别表示两个端点和边权

对于30%的数据,n ≤ 5

对于60%的数据,n ≤ 1000

对于100%的数据,1 ≤ n ≤ 100000, m1 ≤ 2 × n, m2 < n

输出

输出一个数,表示第二类边的权值总和最大可能为多少。(若可能为无穷大则输出-1)

样例输入
5 2 3
1 2
4 5
2 3 100
3 4 100
1 5 1000
样例输出
2000

题解:

将所有第二类边权当作0处理,先构造出生成树。

之后对于不在生成树上的边e,我们尝试加入e,如果构成的环中有一条边大于e则将那条边用e代替更优。

所以我们构造出生成树后,令第二类边权值为x = inf,每次对于一条不在生成树中的边权值w,让环上的第二类边权值x = min(x, w),即树上的链赋值操作,树链剖分即可。

 #include <bits/stdc++.h>

 #define ll long long
#define ull unsigned long long
#define st first
#define nd second
#define pii pair<int, int>
#define pil pair<int, ll>
#define pli pair<ll, int>
#define pll pair<ll, ll>
#define tiii tuple<int, int, int>
#define pw(x) ((1LL)<<(x))
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define sqr(x) ((x)*(x))
#define SIZE(A) ((int)(A.size()))
#define LENGTH(A) ((int)(A.length()))
#define FIN freopen("A.in","r",stdin);
#define FOUT freopen("A.out","w",stdout);
using namespace std;
/***********/ template<typename T>
bool scan (T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ; //EOF
while (c != '-' && (c < '' || c > '') ) c = getchar();
sgn = (c == '-') ? - : ;
ret = (c == '-') ? : (c - '');
while (c = getchar(), c >= '' && c <= '') ret = ret * + (c - '');
ret *= sgn;
return ;
}
template<typename N,typename PN>inline N flo(N a,PN b){return a>=?a/b:-((-a-)/b)-;}
template<typename N,typename PN>inline N cei(N a,PN b){return a>?(a-)/b+:-(-a/b);}
template<typename T>inline int sgn(T a) {return a>?:(a<?-:);}
template<class T> int countbit(const T &n) { return (n==)?:(+countbit(n&(n-))); }
template <class T1, class T2>
bool gmax(T1 &a, const T2 &b) { return a < b? a = b, :;}
template <class T1, class T2>
bool gmin(T1 &a, const T2 &b) { return a > b? a = b, :;}
template <class T> inline T lowbit(T x) {return x&(-x);} template<class T1, class T2>
ostream& operator <<(ostream &out, pair<T1, T2> p) {
return out << "(" << p.st << ", " << p.nd << ")";
}
template<class A, class B, class C>
ostream& operator <<(ostream &out, tuple<A, B, C> t) {
return out << "(" << get<>(t) << ", " << get<>(t) << ", " << get<>(t) << ")";
}
template<class T>
ostream& operator <<(ostream &out, vector<T> vec) {
out << "("; for(auto &x: vec) out << x << ", "; return out << ")";
}
void testTle(int &a){
while() a = a*(ll)a%;
}
const ll inf = 0x3f3f3f3f;
const ll INF = 1e17;
const int mod = 1e9+;
const double eps = 1e-;
const int N = +;
const double pi = acos(-1.0); /***********/ struct Edge{
int x, y, w;
};
Edge edge1[N+N], edge2[N];
vector<pii> ve[N]; int n, m1, m2;
int fa[N];
int findf(int x) { return x == fa[x]? x: fa[x] = findf(fa[x]);} int dfn, f[N], fdis[N], d[N], size[N], son[N], top[N], st[N], en[N];
struct Node {
int maxval;
int tag;
};
Node T[N<<];
int a[N]; void pushup(int rt) {
T[rt].maxval = max(T[rt<<].maxval, T[rt<<|].maxval);
}
void pushdown(int rt) {//区间赋的值递增,之后赋的值必大于之前赋的值,故已有赋值则可跳过
if(T[rt].tag) {
if(!T[rt<<].tag&&T[rt<<].maxval > T[rt].tag)
T[rt<<].tag = T[rt].tag;
if(!T[rt<<|].tag&&T[rt<<|].maxval > T[rt].tag)
T[rt<<|].tag = T[rt].tag;
T[rt].tag = ;
}
if(T[rt].tag) {
if(!T[rt<<].tag&&T[rt<<].maxval > T[rt].tag)
T[rt<<].tag = T[rt].tag;
if(!T[rt<<|].tag&&T[rt<<|].maxval > T[rt].tag)
T[rt<<|].tag = T[rt].tag;
T[rt].tag = ;
}
}
void build(int l, int r, int rt) {
if(l == r) {
T[rt] = {a[l], };
return ;
}
int m = (l+r) >> ;
build(lson);
build(rson);
pushup(rt);
}
void update(int L, int R, int val, int l, int r, int rt) {
if(L <= l&&r <= R) {
if(T[rt].tag == ||T[rt].tag > val) T[rt].tag = val;
return ;
}
pushdown(rt);
int m = (l+r) >> ;
if(L <= m) update(L, R, val, lson);
if(R > m) update(L, R, val, rson);
} void dfs(int x){
size[x] = ;
for(pii e: ve[x]) {
int y = e.st;
if(y != f[x]){
f[y] = x, d[y] = d[x]+;
fdis[y] = e.nd;
dfs(y), size[x] += size[y];
if(size[y] > size[son[x]])
son[x] = y;
}
}
}
void dfs2(int x, int y){
st[x] = ++dfn; top[x] = y; a[dfn] = fdis[x];
if(son[x]) dfs2(son[x], y);
for(pii e: ve[x]) {
int y = e.st;
if(y != son[x]&&y != f[x])
dfs2(y, y);
}
en[x]=dfn;
}
//查询x,y两点的lca
int lca(int x,int y){
for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]]) swap(x, y);
return d[x]<d[y]?x:y;
}
//x是y的祖先,查询x到y方向的第一个点
int lca2(int x, int y){
int t;
while(top[x]!=top[y])t=top[y],y=f[top[y]];
return x==y?t:son[x];
}
//对x到y路径上的点进行操作
void chain(int x, int y, int val){
for(;top[x]!=top[y];x=f[top[x]]){
if(d[top[x]]<d[top[y]]) swap(x, y);
//change(st[top[x]],st[x]);
update(st[top[x]], st[x], val, , n, );
}
if(d[x]<d[y]) swap(x, y);
//change(st[y],st[x]);
update(st[y], st[x], val, , n, );
} long long ans;
bool solve(int l, int r, int rt) {
if(T[rt].maxval != inf) return true;
if(l == r) {
if(T[rt].tag == ) return false;
ans += T[rt].tag;
return true;
}
pushdown(rt);
int m = (l+r) >> ;
return solve(lson) && solve(rson);
}
int main() {
scanf("%d%d%d", &n, &m2, &m1);
for(int i = , x, y; i < m2; i++) {
scanf("%d%d", &x, &y);
edge2[i] = {x, y, };
}
for(int i = , x, y, w; i < m1; i++) {
scanf("%d%d%d", &x, &y, &w);
edge1[i] = {x, y, w};
} sort(edge1, edge1+m1, [](Edge e1, Edge e2) { return e1.w < e2.w; });
for(int i = ; i <= n; i++) fa[i] = i;
for(int i = ; i < m2; i++) {
Edge e = edge2[i];
int fx = findf(e.x), fy = findf(e.y);
if(fx != fy) {
fa[fx] = fy;
ve[e.x].push_back({e.y, inf});
ve[e.y].push_back({e.x, inf});
}
}
vector<Edge> tmp;
for(int i = ; i < m1; i++) {
Edge e = edge1[i];
int fx = findf(e.x), fy = findf(e.y);
if(fx != fy) {
fa[fx] = fy;
ve[e.x].push_back({e.y, e.w});
ve[e.y].push_back({e.x, e.w});
}
else tmp.push_back(e);//将e.x -> e.y路径上的边w = min(w, e.w);
} dfs();
dfs2(, );
build(, n, );
for(Edge e: tmp) {
int x = e.x, y = e.y, w = e.w;
int ancestor = lca(x, y);
if(ancestor != x) {
int xx = lca2(ancestor, x);
chain(xx, x, w);
}
if(ancestor != y) {
int yy = lca2(ancestor, y);
chain(yy, y, w);
}
}
printf("%lld\n", solve(, n, )? ans: -);
return ;
}

[树链剖分]hihocoder1883的更多相关文章

  1. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  2. BZOJ 1984: 月下“毛景树” [树链剖分 边权]

    1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1728  Solved: 531[Submit][Status][Discu ...

  3. codevs 1228 苹果树 树链剖分讲解

    题目:codevs 1228 苹果树 链接:http://codevs.cn/problem/1228/ 看了这么多树链剖分的解释,几个小时后总算把树链剖分弄懂了. 树链剖分的功能:快速修改,查询树上 ...

  4. 并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)

    题目链接 题意: 有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通.有两种操作: 1. 删去a到b的一条边 2. 询问a到b的稳定性 思路: 首先删边考 ...

  5. 树链剖分+线段树 CF 593D Happy Tree Party(快乐树聚会)

    题目链接 题意: 有n个点的一棵树,两种操作: 1. a到b的路径上,给一个y,对于路径上每一条边,进行操作,问最后的y: 2. 修改某个条边p的值为c 思路: 链上操作的问题,想树链剖分和LCT,对 ...

  6. 树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)

    题目链接 题意: 给定一棵树,每条边有黑白两种颜色,初始都是白色,现在有三种操作: 1 u v:u到v路径(最短)上的边都取成相反的颜色 2 u v:u到v路径上相邻的边都取成相反的颜色(相邻即仅有一 ...

  7. bzoj2243树链剖分+染色段数

    终于做了一道不是一眼出思路的代码题(⊙o⊙) 之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱) 实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开 ...

  8. bzoj3631树链剖分

    虽然是水题1A的感觉太爽了O(∩_∩)O~ 题意相当于n-1次树上路径上每个点权值+1,最后问每个点的权值 本来想写线段树,写好了change打算框架打完了再来补,结果打完发现只是区间加和单点查 前缀 ...

  9. BZOJ 3531: [Sdoi2014]旅行 [树链剖分]

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1685  Solved: 751[Submit][Status] ...

随机推荐

  1. ASP.NET Core读取AppSettings (转载)

    今天在把之前一个ASP.NET MVC5的Demo项目重写成ASP.NET Core,发现原先我们一直用的ConfigurationManager.AppSettings[]读取Web.config中 ...

  2. .net core 中使用httpclient,HttpClientFactory的问题

    Microsoft 在.Net Framework 4.5中引入了HttpClient,并且是在.NET服务器端代码中使用Web API的最常用方法.但它有一些严重的问题,如释放HttpClient对 ...

  3. python第二周。2019.4.13

    1, 我绘制大蟒蛇就是..保存也对着呢,你要是打开文件的话,先闪个黑屏,再闪个白屏..自动退出,然后啥都没了. 我觉得是我代码编错了...再来一遍! 这次到可以,但是这个大蟒蛇好像没有回头... 刚才 ...

  4. 2016年总结 - Java程序员

    一 . 技术积累 (1)代码规范 1.1.1.通常的模块分布:一般如果你要实现一个web应用,你从后台将数据展示到前端页面,在一个比较大的公司,你少不了跟其他项目有交集(你调用他的接口,他依赖你的接口 ...

  5. Error【0006】:could not create or update nagios.configtest

    1. 错误背景 在本系列博客<Nagios监控系统部署(源码).md>中(笔记内链:Nagios监控系统部署(源码).md,博客园地址:https://www.cnblogs.com/li ...

  6. 第二次作业 对VC++6.0编译软件的评价

    首先这个软件伴随着我们很长时间了,它是我们一上大学最先接触的,也是应用相当多的一个软件,其实在最初的时候,我对编译软件的理解非常有限,觉得它能实现一个代码的功能十分神奇的一件事情,虽然彼时我们写的代码 ...

  7. [ERROR] Failed to execute goal org.codehaus.mojo:gwt-maven-plugin:2.5.0-rc1:compile (default) on project zeus-web: Command 解决

    在编译maven项目,打包maven packeage -Dmaven.test.skip=TRUE时,报错“[ERROR] Failed to execute goal org.codehaus.m ...

  8. C++高质量编程笔记

    /* * 函数介绍: * 输入参数: * 输出参数: * 返回值 : */ void Function(float x, float y, float z) { - } if (-) { - whil ...

  9. vue 路由传参 params 与 query两种方式的区别

    初学vue的时候,不知道如何在方法中跳转界面并传参,百度过后,了解到两种方式,params 与 query.然后,错误就这么来了:  router文件下index.js里面,是这么定义路由的: { p ...

  10. Python 爬虫 --- urllib

    对于互联网数据,Python 有很多处理网络协议的工具,urllib 是很常用的一种. 一.urllib.request,request 可以很方便的抓取 URL 内容. urllib.request ...