gym 101889I Imperial roads 最小生成树+LCA
题意:
给出一幅无向带权图,q次询问,每次询问都求一棵包含给出的边的最小生成树。
思路:
首先求出最小生成树(kruskal),如果查询的边在最小生成树上,肯定是直接输出最小生成树,如果不在树上,那么这条必须连的边会和生成树形成一个环,我们就要去掉这个环上最大的一条边,就得到了答案(最小生成树是通过局部最优解得到全局最优解的,所以如果这样做,得到的是符合要求的最优解)。
赛中队友提出一个问题,如果有两棵不同的最小生成树那这个做法不就错了吗,但其实如果有两棵最小生成树,这两棵树 相同权值的边的条数是一样的,是同分异构,所以做法还是正确的。
而求环上的最大值,其实是求树上的最大值,所以在做kruskal的时候建立一幅新图,然后用lca求最大值。注意最大值的更新,很容易错。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>
#define CLR(a,b) memset(a,b,sizeof(a))
#define mkp(a,b) make_pair(a,b)
using namespace std;
const int maxn = ;
typedef long long ll;
int n, m, head[maxn], tot, vis[maxn],fa[maxn],deep[maxn],t,f[maxn][],ma[maxn][];
int ans;
struct edge {
int to, w, Next;
edge() {}
edge(int to, int Next, int w) :to(to), Next(Next), w(w) {}
}a[maxn * ];
map<pair<int, int >, int >mp;
struct node {
int u, v, w;
node(int u, int v, int w) :u(u), v(v), w(w) {}
};
vector<node>g;
void addv(int u, int v, int w) {
a[++tot] = { v,head[u],w };
head[u] = tot;
}
void init() {
CLR(head, -);
for (int i = ; i <= n; i++)fa[i] = i;
tot = ;
}
int find(int x)
{
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
inline void baba(int x, int y)
{
int fx = find(x), fy = find(y);
fa[fx] = fy;
}
bool cmp(node &a, node &b)
{
return a.w < b.w;
}
inline void kruskal() {
sort(g.begin(), g.end(), cmp);
for (int i = ; i < m; i++)
{
int x = find(g[i].u);
int y = find(g[i].v);
if (x == y)continue;
addv(g[i].u, g[i].v, g[i].w);
addv(g[i].v, g[i].u, g[i].w);
baba(x, y);
ans += g[i].w;
}
}
inline void bfs() {
queue<int >q;
q.push();
deep[] = ;
while (!q.empty())
{
int x = q.front();
q.pop();
for (int i = head[x]; i != -; i = a[i].Next)
{
int y = a[i].to;
if (deep[y])continue;
deep[y] = deep[x] + ;
f[y][] = x;
ma[y][] = a[i].w;
for (int j = ; j <= t; j++)
{
f[y][j] = f[f[y][j - ]][j - ];
ma[y][j] = max(ma[y][j-], ma[f[y][j - ]][j - ]);
}
q.push(y); }
}
}
int lca(int x, int y)
{
int maxx = ;
if (deep[x] > deep[y])swap(x, y);
for (int i = t; i >= ; i--)
{
if (deep[f[y][i]] >= deep[x]) {
maxx = max(maxx, ma[y][i]);
y = f[y][i];
}
}
if (x == y)return maxx;
for (int i = t; i >= ; i--)
{
if (f[x][i] != f[y][i]) {
maxx = max(maxx, ma[x][i]);
maxx = max(maxx, ma[y][i]);
x = f[x][i], y = f[y][i];
}
}
//printf("debug\n");
maxx=max(maxx,ma[x][]);
maxx=max(maxx,ma[y][]);
return maxx;
}
int main() {
scanf("%d%d", &n, &m);
init();
for(int i=;i<=m;i++)
{
int u, v;
int w;
scanf("%d%d%d", &u, &v, &w);
if (u > v)swap(u, v);
mp[make_pair(u, v)] = w;
g.push_back(node{ u,v,w });
}
kruskal();
t = (int)(log(n) / log()) + ;
bfs();
// for (int i = 1; i <= n; i++)
// {
// printf("i:%d deep:%d\n", i, deep[i]);
// }
int q;
cin >> q;
while (q--)
{
int u, v;
scanf("%d%d", &u, &v);
if (u > v)swap(u, v);
// printf("u:%d v:%d\n", u, v);
// printf("ans:%d lca:%d mp:%d\n",ans,lca(u,v),mp[make_pair(u,v)]);
printf("%d\n", ans - lca(u, v)+mp[make_pair(u,v)]);
}
} /* 5 7
1 2 6
1 3 4
3 4 2
1 5 7
4 5 4
2 4 1
3 5 3
1
4 5 */
gym 101889I Imperial roads 最小生成树+LCA的更多相关文章
- hdu Constructing Roads (最小生成树)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1102 /************************************************* ...
- 【最小生成树+LCA】Imperial roads
http://codeforces.com/gym/101889 I 先跑一遍最小生成树,把经过的边和答案记录下来 对于每个询问的边,显然如果处于MST中,答案不变 如果不在MST中,假设这条边连上了 ...
- GYM 101889I(mst+lca)
最小生成树上倍增询问裸的. const int maxn = 2e5 + 5; int n, m, q; //图 struct Edge { int u, v; ll cost; bool opera ...
- Gym - 101173H Hangar Hurdles (kruskal重构树/最小生成树+LCA)
题目大意:给出一个n*n的矩阵,有一些点是障碍,给出Q组询问,每组询问求两点间能通过的最大正方形宽度. 首先需要求出以每个点(i,j)为中心的最大正方形宽度mxl[i][j],可以用二维前缀和+二分或 ...
- poj 1251 Jungle Roads (最小生成树)
poj 1251 Jungle Roads (最小生成树) Link: http://poj.org/problem?id=1251 Jungle Roads Time Limit: 1000 ...
- bzoj3732: Network--kruskal最小生成树+LCA
这是一道写起来比较顺手的题目 没有各种奇怪的细节,基本就是Kruskal和倍增LCA的模板.. 题目大意:对于一个无向带权图,询问两点之间一条路,使得这条路上的最长边最小,输出最小最长边的的值 那么既 ...
- hdu 1301 Jungle Roads 最小生成树
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1301 The Head Elder of the tropical island of Lagrish ...
- HDU 1102 Constructing Roads (最小生成树)
最小生成树模板(嗯……在kuangbin模板里面抄的……) 最小生成树(prim) /** Prim求MST * 耗费矩阵cost[][],标号从0开始,0~n-1 * 返回最小生成树的权值,返回-1 ...
- hdu Jungle Roads(最小生成树)
Problem Description The Head Elder of the tropical island of Lagrishan has a problem. A burst of for ...
随机推荐
- Github修改项目显示的语言类型
//仓库的根目录下创建 .gitattributes 文件,添加以下代码: *.js linguist-language=java *.css linguist-language=java *.htm ...
- 3-在EasyNetQ上使用SSL连接(黄亮翻译)
EasyNetQ可以通过SSL进行连接.这篇指南的作者Gordon Coulter最初为回应一个提问写的. 首先,你必须仔细依据https://www.rabbitmq.com/ssl.html文章中 ...
- ascii#ascii,对象类中找__repr__,获取其返回值
#!/usr/bin/env python #ascii,对象类中找__repr__,获取其返回值 class Foo : def __repr__(self): return "hello ...
- solr :term 查询, phrase查询, boolean 查询
搜索总体有:term 查询, phrase查询, boolean 查询 1. SOLR搜索覆盖度和准确度保证的三个搜索方式: 保证准确率: AND: Search for two different ...
- solr笔记--solr3.2以后支持document和json两种对象来更新索引
1.json形式(比如把mongodb数据库的导出结果json) <requestHandler name="/update" class="solr.JsonUp ...
- Mybatis的批处理以及执行Update返回行数为负数
项目中用到了批量更新. 在开发当中,可能经常会遇到批量处理这种情况,一般都再在java层面进行, 其本质是节省数据库连接打开关闭的的次数,占用更少的运行内存. 下面先记一下批处理映射吧: mybati ...
- Border Layout
------------------siwuxie095 根面板 contentPane 的默认布局就是 Border Layout B ...
- 【转】nginx的模块变量(HTTP核心模块变量)
nginx的HTTP核心模块引入了大量的变量,可以在指定范围内使用这些变量的值,可以分为三类:一是客户请求头中发送的变量.二是服务器端响应头中的变量,第三是nginx产生的各种变量,我们可以使用$变量 ...
- JavaPersistenceWithMyBatis3笔记-第4章SQL Mappers Using Annotations-001
一. 1.Mapper /** * */ package com.mybatis3.mappers; import org.apache.ibatis.annotations.Select; impo ...
- Python沙盒环境配置
一.简介 本文介绍配置python沙盒环境的方法步骤. 二.安装步骤 1.安装pyenv http://www.cnblogs.com/274914765qq/p/4948530.html 2.安装v ...