玲珑杯 Round15 E咸鱼旅行 最小生成树+BFS

题目链接:http://www.ifrog.cc/acm/problem/1126

maxn = 500005. 不然RE。。。。。

思路:跑一遍最小生成树然后bfs找一下即可。

wa了N次,发现自己并没有真正理解并查集的合并:x = find(u), y = find(v), p[x] = y,等价于先find(u) find(v)之后(需要路径压缩)p[p[u]] = p[v] 或者p[p[v]] = p[u]

不过纯粹自己写kruskal + bfs + 并查 AC的感觉还是很爽的。

代码:

 1 #define maxn 500005
 2 #define maxm 500005
 3 struct node{
 4     int to, val;
 5     node(int t, int v): to(t), val(v) {}
 6 };
 7 int edge[maxm], u[maxm], v[maxm];
 8 int p[maxn], f[maxn];
 9 int n, m, s, t;
10
11 typedef pair<int, int> P;
12 vector<node> G[maxn];
13 queue<node> q;
14 short vis[maxn];
15
16 int findp(int x){
17     return x == p[x]? x: p[x] = findp(p[x]);
18 }
19 int cmp(int i, int j){
20     return edge[i] < edge[j];
21 }
22
23 int kruskal(){
24     for(int i = 0; i < n; i++)
25         G[i].clear();
26     memset(vis, 0, sizeof(vis));
27     int cnt = 0;
28     for(int i = 0; i < n; i++)
29         p[i] = i;
30     for(int i = 0; i < m; i++)
31         f[i] = i;
32     sort(f, f + m, cmp);
33     /*
34     for(int i = 0; i < m; i++)
35         printf("%d\t", f[i]);
36     printf("\n");
37     */
38     for(int ii = 0; ii < m; ii++){
39         int i = f[ii];
40         int tmu = u[i], tmv = v[i];
41         int x = findp(tmu), y = findp(tmv);
42         if(x == y)
43             continue;
44         p[x] = y;
45         G[tmu].push_back(node(tmv, edge[i]));
46         G[tmv].push_back(node(tmu, edge[i]));
47         cnt++;
48         if(cnt >= n - 1)
49             break;
50     }
51     if(cnt != n - 1)
52         return -1;
53
54     q.push(node(s, 0));
55     vis[s] = 1;
56     while(!q.empty()){
57         node tm = q.front();
58         q.pop();
59         if(tm.to == t){
60             return tm.val;
61         }
62         for(int i = 0; i < G[tm.to].size(); i++){
63             node tmn = G[tm.to][i];
64             if(!vis[tmn.to]){
65                 vis[tmn.to] = 1;
66                 q.push(node(tmn.to, max(tmn.val, tm.val)));
67             }
68         }
69     }
70
71     return -1;
72 }
73
74 int main(){
75     scanf("%d %d", &n, &m);
76     for(int i = 0; i < m; i++){
77         int tmu, tmv;
78         scanf("%d %d %d", &tmu, &tmv, &edge[i]);
79         u[i] = --tmu, v[i] = --tmv;
80     }
81     scanf("%d %d", &s, &t);
82     s--, t--;
83     int ans = kruskal();
84     printf("%d\n", ans);
85 }

题目:

1126 - 咸鱼旅行

Time Limit:3s Memory Limit:128MByte

Submissions:539Solved:95

DESCRIPTION

这个地区可以看作是一个无向图,N个点M条边组成。每个边有一个边权。我们定义一条路径的花费,就是这条路径上最大的边权。
现在有一条咸鱼,想从S走到T,徒步旅行。
咸鱼于是找到了你,想让你告诉他从S到T的最小花费。

INPUT

第一行两个整数,N,M。满足(1 <= N <= 10^5, 0 <= M <= 5*10^5)
接下来M行,每行三个整数U,V,C。表示有一个连接U点和V点的边,且边权是C。(1<=C<=10^9)
接下来一个行是两个整数S,T(1<=S,T<=n)

OUTPUT

输出答案,如果S不能到达T,输出-1

SAMPLE INPUT

5 5
1 2 1
2 3 1
3 4 1
4 5 1
5 1 1
1 3

SAMPLE OUTPUT

1

时间: 2024-10-28 10:12:01

玲珑杯 Round15 E咸鱼旅行 最小生成树+BFS的相关文章

poj 3026 Borg Maze(最小生成树+bfs)

题目链接:http://poj.org/problem?id=3026 题意:题意就是从起点开始可以分成多组总权值就是各组经过的路程,每次到达一个‘A'点可以继续分组,但是在路上不能分组 于是就是明显的最小生成树,点与点的距离要用bfs或者dfs求一下.这题bfs要稍微优化一下.不能下暴力的bfs就是两点两点之间 bfs这样会有很多重复的查询会超时,所以要一次性的bfs找到一个点就bfs到底. #include <iostream> #include <algorithm> #in

luogu题解P2502[HAOI2006]旅行--最小生成树变式

题目链接 https://www.luogu.org/problemnew/show/P2502 分析 一个很\(naive\)的做法是从\(s\)到\(t\)双向BFS这当然会TLE 这时我就有个想法就是二分套二分边下标来求得一个比值,同时排序后从小到大枚举每一条边作为最小值,同时再枚举每一条边,如果边权之比小于比值就连起来用并查集维护连通性,可是这个时间复杂度\(O(m^2 log^2m \ \alpha(n))\)过不去QAQ 然后想为什么不直接枚举每条边作为最小值,同时搞一颗以这条边为最

P2502 [HAOI2006]旅行 - 最小生成树【最小比值生成树(雾】

P2502 [HAOI2006]旅行 Sol: 暴力 枚举所有从S到T的路径,然后用maxw/minw更新答案. 时间复杂度:\(O(玄学)\) 正解 观察到边数\(m\leq5000\) 考虑由直接求maxw和minw -> 枚举minw求maxw 由于从S到T的路径上的最大值最小的边一定在最小生成树上(最小生成树的瓶颈路性质),所以我们可以将边从小到大排序,每次枚举边\(e_i\),并将剩下的\(e_i,e_{i+1}\dots e_m\)建最小生成树,当边\(e_k\)使S和T第一次连通时

Borg Maze---poj3026最小生成树+bfs

题目链接:http://poj.org/problem?id=3026 题意:可以理解为给你一个地图上面有S和A的表示一个一个的点,#表示墙,所以需要我们用bfs来计算各点之间的距离: b[i][j] = p;代表map[i][j]的位置的点的编号为p: D[i][j] 代表编号为i和j的距离: #include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #include&

poj 3026 Borg Maze 最小生成树+bfs prim算法

Borg Maze Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8905   Accepted: 2969 Description The Borg is an immensely powerful race of enhanced humanoids from the delta quadrant of the galaxy. The Borg collective is the term used to descr

P2502 [HAOI2006]旅行 最小生成树

思路:枚举边集,最小生成树 提交:1次 题解:(如思路) #include<cstdio> #include<iostream> #include<algorithm> #define R register int using namespace std; #define ull unsigned long long #define ll long long #define pause (for(R i=1;i<=10000000000;++i)) #define

玲珑杯 Round15 A Reverse the light

题目链接:http://www.ifrog.cc/acm/problem/1121 官方题解: 对于每一次的操作,显然其周围的2k个灯不会有状态翻转,否则这次就是无效的,于是转换为简单的动态规划问题.令dp(i)表示将前i+k个灯全部点亮的最小花费,直接转移即可.复杂度为O(n). 恩,然后就是dp一下.然而看了题解之后WA了n次,原因何在? for(int i = n - k; i <= n; i++)  ans = min(ans, dp[i]); 实际上不能这样, n < k的时候就会出

Kuangbin Flying 6最小生成树专题

先说算法:解释算法思想,可以直接从底下的代码复制作为模版 1.Prim.http://baike.baidu.com/link?url=A_L0v3P9Fqk_cmIGZYzA_hFRSOcCGHF8HYISu8HPjmihFhZ_V22oB3agYXCOYI2dY-SELII_ACQaEh5wK7Bmxq 2.Kruskal.http://baike.baidu.com/view/247951.htm 相信百度百科比我讲得绝对好多了. 图论最主要是建图的思想,然后就是上bin神的模版 A -

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

题目大意:给出一个n*n的矩阵,有一些点是障碍,给出Q组询问,每组询问求两点间能通过的最大正方形宽度. 首先需要求出以每个点(i,j)为中心的最大正方形宽度mxl[i][j],可以用二维前缀和+二分或者BFS求. 然后每相邻的两个点建一条权值为min(mxl[i][j],mxl[i'][j'])的边,求出整个图的最小生成树(注意边权要从大到小排序,实际上求出的是边权的“最大生成树”)或者kruskal重构树,对于每组询问(x1,y1),(x2,y2),答案为最小生成树上两点间路径的最小边权,或者