题目传送门

题意:

给出一幅无向带权图,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. hadoop-eclipse-plugin-2.6.0-cdh5.4.0 插件编译

    1.JDK配置 1) 安装jdk 2) 配置环境变量 JAVA_HOME.CLASSPATH.PATH等设置 2.Eclipse 1).下载eclipse-jee-juno-SR2.rar 2).解压 ...

  2. Windows10更新后无限重启

    以安全模式进入系统,禁用或卸载显卡驱动. 重启后重新安装驱动.

  3. hibernate学习笔记(3)hibernate常用配置以及session对象

    更改hibernate.cfg.xml的内容,常用配置有: <!--  把hibernate运行时的SQL语句显示到控制台  --> <property name="sho ...

  4. 浅析大数据的技术生态圈(Hadoop,hive,spark)

    大数据本身是个很宽泛的概念,Hadoop生态圈(或者泛生态圈)基本上都是为了处理超过单机尺度的数据处理而诞生的.你可以把它比作一个厨房所以需要的各种工具.锅碗瓢盆,各有各的用处,互相之间又有重合.你可 ...

  5. Codeforces #505(div1+div2) D Recovering BST

    题意:给你一个升序的数组,元素之间如果gcd不为1可以建边,让你判断是否可以建成一颗二叉搜索树. 解法:dp,首先建图,然后进行状态转移.因为如果点k左端与i相连,右端与k相连,则i和k可以相连,同时 ...

  6. JSON数据格式简介

    ---------------siwuxie095                         JSON 简介     JSON:JavaScript 对象表示法(JavaScript Objec ...

  7. C++面向对象类的实例题目二

    题目描述: 编写一个程序,设计一个产品类Product,其定义如下: class Product { public: Product(char *n,int p,int q); //构造函数 ~Pro ...

  8. HDOJ 1097 A hard puzzle

    Problem Description lcy gives a hard puzzle to feng5166,lwg,JGShining and Ignatius: gave a and b,how ...

  9. HTML和CSS入门教程

    慕课网上面的HTML+CSS基础课程感觉非常适合入门.

  10. 前端学习笔记2017.6.21-html是个什么东西

    html有两种意思,html语言和html格式 html语言是一种面向人类的计算机语言,这是啥意思?人类用html这种语言描述出一个网页的样子,浏览器解析这个语言并展示出来. html格式是一种文件格 ...