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 ...
随机推荐
- GET与POST方法
HTTP中的GET,POST,PUT,DELETE对应着对这个资源的查,改,增,删4个操作.GET一般用于获取/查询资源信息,而POST一般用于更新资源信息. 1.根据HTTP规范,GET用于信息获取 ...
- K-D TREE算法原理及实现
博客转载自:https://leileiluoluo.com/posts/kdtree-algorithm-and-implementation.html k-d tree即k-dimensional ...
- Flash of Unstyled Content (FOUC)
在这次的产品发布中,客户发现了一个问题,就是在Firefox浏览器中,页面在加载的时候,出现没有样式的内容一闪而过的现象.其实,在测试过程中,我们也看到了类似的问题,但是并没有意识到这是一个问题,以为 ...
- C语言-郝斌笔记-006排序及查找
1. int partion(int *a, int low, int high) { int value = a[low]; int t; while (low < high) { while ...
- Python 使用其他邮件服务商的 SMTP 访问(QQ、网易、163、Google等)发送邮件
163邮箱SMTP授权 使用Python SMTP发送邮件 # -*- coding:utf-8 -*- from __future__ import print_function __author_ ...
- Luogu 1514 [NOIP2010] 引水入城
我就是过来开心一下……这道题从开坑以来已经堆积了大半年了……今天才发现广搜一直写挂…… 丢个线段覆盖的模板,设$f_{i}$表示覆盖区间[1, i]的最小代价,$g_{i, j}$表示覆盖区间[i, ...
- 无法认识patch请求
Content-Type: application/vnd.api+jsonbase64:账号密码的设置总结:该及时消化的知识,就应该当时消化.不能拖.注意细节,一个小细节的疏忽,导致自己几乎一天的时 ...
- HDU 3001 Travelling (状压DP + BFS)
题意:有一个人要去旅游,他想要逛遍所有的城市,但是同一个城市又不想逛超过2次.现在给出城市之间的来往路费,他可以选择任意一个点为起点. 问逛遍所有城市的最低路费是多少. 析:用三进制表示每个城市的访问 ...
- 使用docker的kms服务器激活office2016专业增强版
我安装了office2016专业增强版,使用自己搭建的kms激活服务器无法激活,回来使用了一下脚本: 感谢,rainfarm的博主.博客地址:http://blog.sina.com.cn/s/blo ...
- 关于AJAX异步加载节点无法触发点击事件问题的解决方式
做练习的过程中遇到一个问题,使用AJAX异步新增一个节点,无法触发点击事件,经过查阅之后知道一个方式,使用JS的委托事件,在此做一个记录. $(document).on('click', '.recr ...