NOIP2013D1T3货车运输(最大生成树+倍增lca)
这道题,先用kruskal求一遍图中的最大生成树。
然后,倍增求lca,求lca的同时求出边权的最小值。
#include <cstring>
#include <cstdio>
#include <algorithm> int n, m, cnt, q, t, k;
int f[], head[], p[][], minn[][], deep[];
bool vis[];
struct node
{
int x, y, z;
}tree[];
struct Node
{
int next, to, val;
}edge[]; inline void add(int a, int b, int c)
{
edge[cnt].val = c;
edge[cnt].to = b;
edge[cnt].next = head[a];
head[a] = cnt++;
} inline int father(int a)
{
return a == f[a] ? a : f[a] = father(f[a]);
} inline bool cmp(node a, node b)
{
return a.z > b.z;
} void kruskal()
{
int i;
for(i = ; i <= m; i++) scanf("%d %d %d", &tree[i].x, &tree[i].y, &tree[i].z);
for(i = ; i <= n; i++) f[i] = i;
std::sort(tree + , tree + m + , cmp);
for(i = ; i <= m; i++)
{
int fa = father(tree[i].x), fb = father(tree[i].y);
if(fa != fb)
{
f[fa] = fb;
add(tree[i].x, tree[i].y, tree[i].z);
add(tree[i].y, tree[i].x, tree[i].z);
}
if(k == n - ) break;
}
} void dfs(int i)
{
int j;
vis[i] = ;
for(j = head[i]; j != -; j = edge[j].next)
if(!vis[edge[j].to])
{
deep[edge[j].to] = deep[i] + ;
p[edge[j].to][] = i;
minn[edge[j].to][] = edge[j].val;
dfs(edge[j].to);
}
} void init()
{
int i, j;
for(j = ; ( << j) <= n; j++)
for(i = ; i <= n; i++)
{
p[i][j] = p[p[i][j - ]][j - ];
minn[i][j] = std::min(minn[i][j - ], minn[p[i][j - ]][j - ]);
}
} int lca(int a, int b)
{
int i, j, ret = ;
if(deep[a] < deep[b]) std::swap(a, b);
for(i = ; ( << i) <= deep[a]; i++);
i--;
for(j = i; j >= ; j--)
if(deep[a] - ( << j) >= deep[b])
{
ret = std::min(ret, minn[a][j]);
a = p[a][j];
}
if(a == b) return ret;
for(j = i; j >= ; j--)
if(p[a][j] != p[b][j])
{
ret = std::min(ret, std::min(minn[a][j], minn[b][j]));
a = p[a][j];
b = p[b][j];
}
ret = std::min(ret, std::min(minn[a][], minn[b][]));
return ret;
} int main()
{
int i, j, x1, y1;
scanf("%d %d", &n, &m);
memset(head, -, sizeof(head));
//memset(minn, 127 / 3, sizeof(minn));
kruskal();
for(i = ; i <= n; i++)
if(!vis[i])
{
deep[i] = ;
dfs(i);
}
init();
scanf("%d", &q);
for(i = ; i <= q; i++)
{
scanf("%d %d", &x1, &y1);
if(father(x1) != father(y1)) printf("-1\n");
else printf("%d\n", lca(x1, y1));
}
return ; }
换了写法
惨啊,
i >= 0 我居然nc的用 i 代替
应该是 i >= 1 用 i 代替
#include <cstdio>
#include <cstring>
#include <algorithm> const int MAXN = , MAXM = , INF = ;
int n, m, q, cnt, tot;
int head[MAXM], to[MAXM << ], next[MAXM << ], val[MAXM << ];
int f1[MAXN], f[MAXN][], min[MAXN][], deep[MAXN]; struct node
{
int x, y, z;
}p[MAXM]; inline bool cmp(node a, node b)
{
return a.z > b.z;
} inline void add(int x, int y, int z)
{
to[cnt] = y;
val[cnt] = z;
next[cnt] = head[x];
head[x] = cnt++;
} inline int find(int x)
{
return x == f1[x] ? x : f1[x] = find(f1[x]);
} inline int Min(int x, int y)
{
return x < y ? x : y;
} inline void swap(int &x, int &y)
{
x ^= y ^= x ^= y;
} inline void dfs(int u)
{
int i, v;
deep[u] = deep[f[u][]] + ;
for(i = ; f[u][i]; i++)
f[u][i + ] = f[f[u][i]][i],
min[u][i + ] = Min(min[u][i], min[f[u][i]][i]);
for(i = head[u]; i ^ -; i = next[i])
{
v = to[i];
if(!deep[v])
{
f[v][] = u;
min[v][] = val[i];
dfs(v);
}
}
} inline int lca(int x, int y)
{
int i, ans = INF;
if(deep[x] < deep[y]) swap(x, y);
for(i = ; i >= ; i--)
if(deep[f[x][i]] >= deep[y])
ans = Min(ans, min[x][i]), x = f[x][i];
if(x == y) return ans == INF ? - : ans;
for(i = ; i >= ; i--)
if(f[x][i] ^ f[y][i])
ans = Min(ans, min[x][i]),
ans = Min(ans, min[y][i]),
x = f[x][i], y = f[y][i];
ans = Min(ans, min[x][]);
ans = Min(ans, min[y][]);
return ans == INF ? - : ans;
} int main()
{
//freopen("truck.in", "r", stdin);
//freopen("truck.out", "w", stdout);
int i, x, y, fx, fy;
scanf("%d %d", &n, &m);
memset(head, -, sizeof(head));
memset(min, / , sizeof(min));
for(i = ; i <= m; i++) scanf("%d %d %d", &p[i].x, &p[i].y, &p[i].z);
std::sort(p + , p + m + , cmp);
for(i = ; i <= n; i++) f1[i] = i;
for(i = ; i <= m; i++)
{
fx = find(p[i].x);
fy = find(p[i].y);
if(fx ^ fy)
{
f1[fx] = fy;
tot++;
add(p[i].x, p[i].y, p[i].z);
add(p[i].y, p[i].x, p[i].z);
}
if(tot == n - ) break;
}
for(i = ; i <= n; i++)
if(!deep[i])
dfs(i);
scanf("%d", &q);
for(i = ; i <= q; i++)
{
scanf("%d %d", &x, &y);
if(find(x) ^ find(y)) puts("-1");
else printf("%d\n", lca(x, y));
}
return ;
}
NOIP2013D1T3货车运输(最大生成树+倍增lca)的更多相关文章
- TZOJ 4848 货车运输(最大生成树+倍增lca)
描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多 ...
- $Noip2013/Luogu1967$ 货车运输 最大生成树+倍增$lca$
$Luogu$ $Sol$ 首先当然是构建一棵最大生成树,然后对于一辆货车的起点和终点倍增跑$lca$更新答案就好.记得预处理倍增的时候不仅要处理走了$2^i$步后是那个点,还有这中间经过的路径权值的 ...
- 【NOIP2013】货车运输 最大生成树+倍增
题目大意:给你一张n个点m条边的图,有q次询问,每次让你找出一条从x至y的路径,使得路径上经过的边的最小值最大,输出这个最大的最小值. 显然,经过的路径必然在这张图的最大生成树上. 我们求出这个图的最 ...
- 「NOIP2013」「LuoguP1967」货车运输(最大生成树 倍增 LCA
题目描述 AA国有nn座城市,编号从 11到nn,城市之间有 mm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最 ...
- 货车运输(最大生成树+倍增LCA)
看到第一篇题解的神奇码风--我决定发一篇码风正常的题解造福人类 这题的做法也非常经典,最大生成树\(+LCA\),相当于先贪心一下,在LCA的时候记录一下当前最小的边权 顺便吐槽一下最后一个测试点: ...
- 【洛谷1967】货车运输(最大生成树+倍增LCA)
点此看题面 大致题意: 有\(n\)个城市和\(m\)条道路,每条道路有一个限重.多组询问,每次询问从\(x\)到\(y\)的最大载重为多少. 一个贪心的想法 首先,让我们来贪心一波. 由于要求最大载 ...
- 货车运输 noip2013 luogu P1967 (最大生成树+倍增LCA)
luogu题目传送门! 首先,题目让我们求每个货车的最大运输量,翻译一下就是求路径上边权最小的边. 利用一下贪心思想可知,所有货车肯定都会尽量往大的边走. 进一步翻译,即为有一些小边货车根本不会走,或 ...
- 【NOIP2013】货车运输 最大生成树+LCA
题目描述 AA国有nn座城市,编号从 1到n,城市之间有m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重 ...
- Luogu1967 NOIP2013 货车运输 最大生成树、倍增
传送门 题意:给出一个$N$个节点.$M$条边的图,$Q$次询问,每一次询问两个点之间的所有可行路径中经过的边的边权的最小值中的最大值.$N \leq 10000 , M \leq 50000 , Q ...
随机推荐
- 【转】Java集合:HashMap源码剖析
Java集合:HashMap源码剖析 一.HashMap概述二.HashMap的数据结构三.HashMap源码分析 1.关键属性 2.构造方法 3.存储数据 4.调 ...
- logging日志过滤和日志文件自动截取
1.日志过滤 import logging class IgnoreFilter(logging.Filter): def filter(self,record): return "girl ...
- Linux安装技巧--安装Uuntu与windows8/10共存
1.准备安装双系统所需工具. 系统: Linux有众多的衍生版本,选择一个自己喜欢的版本下载,建议新手上ubuntu吧,中文教程较多,出了问题容易解决,等到熟悉了再用其他的也行,新手的话ubuntu也 ...
- sprintf使用时需要注意的问题
- 关于ie的内存泄漏与javascript内存释放
最近做一个公司的业务系统,公司要求能尽可能的与c/s近似,也就是如c/s一样,点击文本框可以弹出此项目的相关内容,进行选择输入. 我使用了弹出窗口,然后在子窗口双击选中项目,把选中的值返回给父 ...
- SQLite与MySQL、SQLServer等异构数据库之间的数据同步
SQLite DBSync是开源嵌入式数据库SQLite的数据同步引擎,实现了SQLite与SQLite数据库之间以及SQLite与异构数据库(Oracle.MySQL.SQLServer)之间的增量 ...
- SQLite – LIMIT子句
SQLite - LIMIT子句 SQLite LIMIT子句是用来限制SELECT语句返回的数据量. 语法: SELECT语句.LIMIT子句的基本语法如下: SELECT column1, col ...
- uva1627 Team them up!
注意这题要求互相认识不认识的人之间连一条线一个人在组1,那么不认识(互相认识)的人就在组0:同时这些人不认识的人就在组1.每个联通分量都可以独立推导,遇到矛盾则无解一个联通分量有一个核心,其他的点是分 ...
- 解决VSCode中使用vetur插件格式化vue文件时,js代码会自动加上冒号和分号
解决VSCode中使用vetur插件格式化vue文件时,js代码会自动加上冒号和分号 在设置中把"vetur.format.defaultFormatter.js": " ...
- Zend Studio 修改“代码字体和大小”