传送门

这道题,先用kruskal求一遍图中的最大生成树。

然后,倍增求lca,求lca的同时求出边权的最小值。

#include <cstring>
#include <cstdio>
#include <algorithm>int n, m, cnt, q, t, k;
int f[10001], head[100001], p[10001][21], minn[10001][21], deep[10001];
bool vis[10001];
struct node
{int x, y, z;
}tree[100001];
struct Node
{int next, to, val;
}edge[100001];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 = 1; i <= m; i++)    scanf("%d %d %d", &tree[i].x, &tree[i].y, &tree[i].z);for(i = 1; i <= n; i++) f[i] = i;std::sort(tree + 1, tree + m + 1, cmp);for(i = 1; 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 - 1) break;}
}void dfs(int i)
{int j;vis[i] = 1;for(j = head[i]; j != -1; j = edge[j].next)if(!vis[edge[j].to]){deep[edge[j].to] = deep[i] + 1;p[edge[j].to][0] = i;minn[edge[j].to][0] = edge[j].val;dfs(edge[j].to);}
}void init()
{int i, j;for(j = 1; (1 << j) <= n; j++)for(i = 1; i <= n; i++){p[i][j] = p[p[i][j - 1]][j - 1];minn[i][j] = std::min(minn[i][j - 1], minn[p[i][j - 1]][j - 1]);}
}int lca(int a, int b)
{int i, j, ret = 707406378;if(deep[a] < deep[b]) std::swap(a, b);for(i = 0; (1 << i) <= deep[a]; i++);i--;for(j = i; j >= 0; j--)if(deep[a] - (1 << j) >= deep[b]){ret = std::min(ret, minn[a][j]);a = p[a][j];}if(a == b) return ret;for(j = i; j >= 0; 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][0], minn[b][0]));return ret;
}int main()
{int i, j, x1, y1;scanf("%d %d", &n, &m);memset(head, -1, sizeof(head));//memset(minn, 127 / 3, sizeof(minn));
    kruskal();for(i = 1; i <= n; i++)if(!vis[i]){deep[i] = 1;dfs(i);}init();scanf("%d", &q);for(i = 1; i <= q; i++){scanf("%d %d", &x1, &y1);if(father(x1) != father(y1)) printf("-1\n");else printf("%d\n", lca(x1, y1));}return 0;}

View Code

换了写法

惨啊,

i >= 0 我居然nc的用 i 代替

应该是 i >= 1 用 i 代替

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4
  5 const int MAXN = 10001, MAXM = 50001, INF = 707406378;
  6 int n, m, q, cnt, tot;
  7 int head[MAXM], to[MAXM << 1], next[MAXM << 1], val[MAXM << 1];
  8 int f1[MAXN], f[MAXN][21], min[MAXN][21], deep[MAXN];
  9
 10 struct node
 11 {
 12     int x, y, z;
 13 }p[MAXM];
 14
 15 inline bool cmp(node a, node b)
 16 {
 17     return a.z > b.z;
 18 }
 19
 20 inline void add(int x, int y, int z)
 21 {
 22     to[cnt] = y;
 23     val[cnt] = z;
 24     next[cnt] = head[x];
 25     head[x] = cnt++;
 26 }
 27
 28 inline int find(int x)
 29 {
 30     return x == f1[x] ? x : f1[x] = find(f1[x]);
 31 }
 32
 33 inline int Min(int x, int y)
 34 {
 35     return x < y ? x : y;
 36 }
 37
 38 inline void swap(int &x, int &y)
 39 {
 40     x ^= y ^= x ^= y;
 41 }
 42
 43 inline void dfs(int u)
 44 {
 45     int i, v;
 46     deep[u] = deep[f[u][0]] + 1;
 47     for(i = 0; f[u][i]; i++)
 48         f[u][i + 1] = f[f[u][i]][i],
 49         min[u][i + 1] = Min(min[u][i], min[f[u][i]][i]);
 50     for(i = head[u]; i ^ -1; i = next[i])
 51     {
 52         v = to[i];
 53         if(!deep[v])
 54         {
 55             f[v][0] = u;
 56             min[v][0] = val[i];
 57             dfs(v);
 58         }
 59     }
 60 }
 61
 62 inline int lca(int x, int y)
 63 {
 64     int i, ans = INF;
 65     if(deep[x] < deep[y]) swap(x, y);
 66     for(i = 20; i >= 0; i--)
 67         if(deep[f[x][i]] >= deep[y])
 68             ans = Min(ans, min[x][i]), x = f[x][i];
 69     if(x == y) return ans == INF ? -1 : ans;
 70     for(i = 20; i >= 0; i--)
 71         if(f[x][i] ^ f[y][i])
 72             ans = Min(ans, min[x][i]),
 73             ans = Min(ans, min[y][i]),
 74             x = f[x][i], y = f[y][i];
 75     ans = Min(ans, min[x][0]);
 76     ans = Min(ans, min[y][0]);
 77     return ans == INF ? -1 : ans;
 78 }
 79
 80 int main()
 81 {
 82     //freopen("truck.in", "r", stdin);
 83     //freopen("truck.out", "w", stdout);
 84     int i, x, y, fx, fy;
 85     scanf("%d %d", &n, &m);
 86     memset(head, -1, sizeof(head));
 87     memset(min, 127 / 3, sizeof(min));
 88     for(i = 1; i <= m; i++) scanf("%d %d %d", &p[i].x, &p[i].y, &p[i].z);
 89     std::sort(p + 1, p + m + 1, cmp);
 90     for(i = 1; i <= n; i++) f1[i] = i;
 91     for(i = 1; i <= m; i++)
 92     {
 93         fx = find(p[i].x);
 94         fy = find(p[i].y);
 95         if(fx ^ fy)
 96         {
 97             f1[fx] = fy;
 98             tot++;
 99             add(p[i].x, p[i].y, p[i].z);
100             add(p[i].y, p[i].x, p[i].z);
101         }
102         if(tot == n - 1) break;
103     }
104     for(i = 1; i <= n; i++)
105         if(!deep[i])
106             dfs(i);
107     scanf("%d", &q);
108     for(i = 1; i <= q; i++)
109     {
110         scanf("%d %d", &x, &y);
111         if(find(x) ^ find(y)) puts("-1");
112         else printf("%d\n", lca(x, y));
113     }
114     return 0;
115 }

View Code

转载于:https://www.cnblogs.com/zhenghaotian/p/6667614.html

NOIP2013D1T3货车运输(最大生成树+倍增lca)相关推荐

  1. poj1330|bzoj3732|noip2013 货车运输 kruskal+倍增lca

    学了一早上倍增,感觉lca还是tarjan好写. poj1330 1 #include <stdio.h> 2 #include <string.h> 3 #include & ...

  2. 洛谷T1967 货车运输 Kruskal最大生成树倍增LCA

    这题的题意是:对于每组x.y,求x到y路径上最小边权的最大值. 于是可以使用最大生成树,因为最大生成树满足性质:生成树中最小边权最大,且任意两点间路径上最小边权最大. 有了树之后,要求路径,那就要考虑 ...

  3. 洛谷1967 火车运输 kruskal求最大生成树 倍增LCA维护最小值

    传送门 其实NOIP某些年的第三题也并不是很难嘛... 题目分析: 题目中要求求出某两点之间可以运输的最大重量,也就是这两个点的某条路径上边权最小的边的权值的最大值 很显然,题目中的运输最大重量与选择 ...

  4. CodeVS3287[NOIP2013] 货车运输【Kruskal+倍增求LCA】

    题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过 ...

  5. P1967 货车运输( 最大生成树+LCA or Kruskal重构树)

    至于为什么要用最大生成树!? 理由:因为问最大载重,如果要加大载重的话,对于选择的路肯定权重越大越好,所以贪心地想,得用到最大生成树.然后两点之间的最大载重用LCA去寻找就可以了. 最大生成树+LCA ...

  6. P1967,ssl2267-货车运输【树上倍增LCA,最小生成树变形kruskal】

    正题 题目链接: https://www.luogu.org/problemnew/show/P1967 大意 一个无向图,每个边有个权值,若干个询问,求两个点之间的一条最短路是这条最短路上的最小权值 ...

  7. NOIP2013 D1T3 货车运输 倍增LCA OR 并查集按秩合并

    思路: Kruskal求最大生成树+倍增LCA // by SiriusRen #include <cstdio> #include <cstring> #include &l ...

  8. 洛古1967 货车运输

    具体思路: 最大生成树 + 倍增LCA 首先感谢tqc大佬为我的耐心修改代码(你可能是改了个shi- -) 贴代码 include include include include include us ...

  9. 货车运输题解 最大生成树+lca

    3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条 ...

最新文章

  1. Python 报错解决:AttributeError: 'module' object has no attribute 'SSL_ST_INIT'
  2. Win10 安装msi 提示2502、2503的错误代码 -- 命令提示符(管理员) -- msiexec /package...
  3. 哪些医药企业使用SAP系统呢?
  4. 数据结构:试设计一个算法,改造一个带表头结点的双向链表,所有结点的原有次序保持在各个结点的右链域rLink中,并利用左链域ILink把所有结点按照其值从小到大的顺序连接起来
  5. RabbitMQ入门(二)-helloworld
  6. 理解快速生成树协议(RSTP)(二)
  7. pytorch学习笔记(十七):Read-Write
  8. java web应用程序_说说Java Web中的Web应用程序|乐字节
  9. XDeepFM高阶特征交互,特征交互:一种极深因子分解机模型
  10. HBase的两种协处理器
  11. Android源码:1、如何下载源码详解(一)
  12. 基于朴素贝叶斯的新闻分类
  13. [Luogu P3164] [BZOJ 3503] [CQOI2014]和谐矩阵
  14. latex设置times new roman新罗马字体
  15. msp430开发环境安装
  16. leetcode 717. 1比特与2比特字符(python)
  17. dnfdpl服务器维护了,2019DNF心悦DPL活动地址 DNF心悦DPL活动网址及奖励一览
  18. TextView实现水平滚动
  19. jenkins 403 No valid crumb was included in the request 解决方案
  20. 贝壳金服 TiDB 在线跨机房迁移实践

热门文章

  1. 图论算法 最短路程_从网页排序看图论的重要应用
  2. 与c++ 进行最简单的进程通信
  3. fetch ajax cros,由 Fetch 跨域 看 CORS
  4. pytorch cpu版本安装_pytorch深度学习框架--gpu和cpu的选择
  5. [大学回忆录]尧山学习生活总结
  6. u-boot移植随笔:System.map文件格式
  7. 【nexus】nexus 仓库组的概念 以及相关配置 代码发布相关
  8. 【Elasticsearch】es Timelion是Kibana中时间序列的可视化工具
  9. 【Elasticsearch】ES Elasticsearch查询优化
  10. 【Java】Java 集合相关的博客积累