玲珑杯 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

 

posted @ 2017-06-02 09:47  EricJeffrey  阅读(161)  评论(0编辑  收藏  举报