题目传送门

题意:

给出一幅无向带权图,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的更多相关文章

  1. hdu Constructing Roads (最小生成树)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1102 /************************************************* ...

  2. 【最小生成树+LCA】Imperial roads

    http://codeforces.com/gym/101889 I 先跑一遍最小生成树,把经过的边和答案记录下来 对于每个询问的边,显然如果处于MST中,答案不变 如果不在MST中,假设这条边连上了 ...

  3. GYM 101889I(mst+lca)

    最小生成树上倍增询问裸的. const int maxn = 2e5 + 5; int n, m, q; //图 struct Edge { int u, v; ll cost; bool opera ...

  4. Gym - 101173H Hangar Hurdles (kruskal重构树/最小生成树+LCA)

    题目大意:给出一个n*n的矩阵,有一些点是障碍,给出Q组询问,每组询问求两点间能通过的最大正方形宽度. 首先需要求出以每个点(i,j)为中心的最大正方形宽度mxl[i][j],可以用二维前缀和+二分或 ...

  5. poj 1251 Jungle Roads (最小生成树)

    poj   1251  Jungle Roads  (最小生成树) Link: http://poj.org/problem?id=1251 Jungle Roads Time Limit: 1000 ...

  6. bzoj3732: Network--kruskal最小生成树+LCA

    这是一道写起来比较顺手的题目 没有各种奇怪的细节,基本就是Kruskal和倍增LCA的模板.. 题目大意:对于一个无向带权图,询问两点之间一条路,使得这条路上的最长边最小,输出最小最长边的的值 那么既 ...

  7. hdu 1301 Jungle Roads 最小生成树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1301 The Head Elder of the tropical island of Lagrish ...

  8. HDU 1102 Constructing Roads (最小生成树)

    最小生成树模板(嗯……在kuangbin模板里面抄的……) 最小生成树(prim) /** Prim求MST * 耗费矩阵cost[][],标号从0开始,0~n-1 * 返回最小生成树的权值,返回-1 ...

  9. hdu Jungle Roads(最小生成树)

    Problem Description The Head Elder of the tropical island of Lagrishan has a problem. A burst of for ...

随机推荐

  1. GET与POST方法

    HTTP中的GET,POST,PUT,DELETE对应着对这个资源的查,改,增,删4个操作.GET一般用于获取/查询资源信息,而POST一般用于更新资源信息. 1.根据HTTP规范,GET用于信息获取 ...

  2. K-D TREE算法原理及实现

    博客转载自:https://leileiluoluo.com/posts/kdtree-algorithm-and-implementation.html k-d tree即k-dimensional ...

  3. Flash of Unstyled Content (FOUC)

    在这次的产品发布中,客户发现了一个问题,就是在Firefox浏览器中,页面在加载的时候,出现没有样式的内容一闪而过的现象.其实,在测试过程中,我们也看到了类似的问题,但是并没有意识到这是一个问题,以为 ...

  4. C语言-郝斌笔记-006排序及查找

    1. int partion(int *a, int low, int high) { int value = a[low]; int t; while (low < high) { while ...

  5. Python 使用其他邮件服务商的 SMTP 访问(QQ、网易、163、Google等)发送邮件

    163邮箱SMTP授权 使用Python SMTP发送邮件 # -*- coding:utf-8 -*- from __future__ import print_function __author_ ...

  6. Luogu 1514 [NOIP2010] 引水入城

    我就是过来开心一下……这道题从开坑以来已经堆积了大半年了……今天才发现广搜一直写挂…… 丢个线段覆盖的模板,设$f_{i}$表示覆盖区间[1, i]的最小代价,$g_{i, j}$表示覆盖区间[i, ...

  7. 无法认识patch请求

    Content-Type: application/vnd.api+jsonbase64:账号密码的设置总结:该及时消化的知识,就应该当时消化.不能拖.注意细节,一个小细节的疏忽,导致自己几乎一天的时 ...

  8. HDU 3001 Travelling (状压DP + BFS)

    题意:有一个人要去旅游,他想要逛遍所有的城市,但是同一个城市又不想逛超过2次.现在给出城市之间的来往路费,他可以选择任意一个点为起点. 问逛遍所有城市的最低路费是多少. 析:用三进制表示每个城市的访问 ...

  9. 使用docker的kms服务器激活office2016专业增强版

    我安装了office2016专业增强版,使用自己搭建的kms激活服务器无法激活,回来使用了一下脚本: 感谢,rainfarm的博主.博客地址:http://blog.sina.com.cn/s/blo ...

  10. 关于AJAX异步加载节点无法触发点击事件问题的解决方式

    做练习的过程中遇到一个问题,使用AJAX异步新增一个节点,无法触发点击事件,经过查阅之后知道一个方式,使用JS的委托事件,在此做一个记录. $(document).on('click', '.recr ...