标签:连接 超过 提示 cst 递增 first 使用 思维 name
C国由n个小岛组成,为了方便小岛之间联络,C国在小岛间建立了m座大桥,每座大桥连接两座小岛。两个小岛间可能存在多座桥连接。然而,由于海水冲刷,有一些大桥面临着不能使用的危险。如果两个小岛间的所有大桥都不能使用,则这两座小岛就不能直接到达了。然而,只要这两座小岛的居民能通过其他的桥或者其他的小岛互相到达,他们就会安然无事。但是,如果前一天两个小岛之间还有方法可以到达,后一天却不能到达了,居民们就会一起发起抗议。
现在C国的国王已经知道了每座桥能使用的天数,超过这个天数就不能使用了。现在他想知道居民们一共会发起多少次抗议。
4 4 1 2 2 1 3 2 2 3 1 3 4 3
2
/** 分析:该题是,判断第i天的非连通区域和第i+1天的非连通区域 若第i+1天的非连通区域比第i天的非连通区域多 说明:桥断了、居民抗议、cnt ++ 所以我们可以逆向思维 <断桥 <==> 修桥>(将数据按照天数由大到小排列): 若将两个桥 my_join 的时候桥没有连通 cnt ++ <同时要考虑是否和上一个数据是同一天(因为居民每天最大抗议一次)> 数据结构:并查集 模板: pre [100005]; void init () { for (int i = 1; i <= n; ++ i) { pre [i] = i; } return ; } int my_find (int x) { int n = x; while (n != pre [n]) { n = pre [n]; } int i = x, j; while (n != pre [i]) { j = pre [i]; pre [i] = n; i = j; } } bool my_join (int a, int b) { int n1 = my_find (a), n2 = my_find (b); if (n1 != n2) { pre [n1] = n2; return true; } else { return false; } } **/
C/C++代码实现:
#include <iostream> #include <cstring> #include <algorithm> #include <cmath> #include <cstdio> #include <stack> #include <queue> #include <map> using namespace std; int n, m, pre [10005]; struct node { int x, y, w; }P [100005]; void init () { for (int i = 1; i <= n; ++ i) { pre [i] = i; } return ; } bool cmp (node a, node b) { return a.w > b.w; } int my_find (int x) { int n = x; while (n != pre [n]) { n = pre [n]; } int i = x, j; while (n != pre [i]) { j = pre [i]; pre [i] = n; i = j; } return n; } bool my_join (int a, int b) { int n1 = my_find (a), n2 = my_find (b); if (n1 != n2) { pre [n1] = n2; return true; } return false; } int main () { while (~scanf ("%d%d", &n, &m)) { init(); int cnt = 0, my_first = -1; for (int i = 0; i < m; ++ i) { scanf ("%d%d%d", &P[i].x, &P[i].y, &P[i].w); } sort (P, P + m, cmp); for (int i = 0; i < m; ++ i) { if (my_join (P[i].x, P[i].y) && my_first != P[i].w) { ++ cnt; my_first = P[i].w; // 每一天最多抗议1次 } } printf ("%d\n", cnt); } }
标签:连接 超过 提示 cst 递增 first 使用 思维 name
原文地址:https://www.cnblogs.com/GetcharZp/p/8974663.html