【GDOI2017第二轮模拟day1】公路建设(克鲁斯卡尔最小生成树+线段树+归并)
2017-12-22 20:49
471 查看
题目大意:
给出n个点,m条边。q组询问,每次询问编号在[l..r]范围的所有边做克鲁斯卡尔最小生成树的代价。
1<=n<=100,1<=m<=100000,1<=q<=15000
题解:
n好小啊。可不可以线段树啊。
套个归并就可以啊。
莫队+lct可不可以啊。
时间复杂度:O(αmn+α q log m n)
Code:
#include<cstdio> #include<cstring> #define fo(i, x, y) for(int i = x; i <= y; i ++) using namespace std; const int N = 1e5 + 5; int n, m, q; struct edge { int u, v, c; } e ; int f ; int find(int x) {return f[x] == x ? x : (f[x] = find(f[x]));} struct tree { int s, d[100]; } t[N * 4]; void He(tree &t, tree a, tree b) { t.s = t.d[0] = 0; fo(i, 1, n) f[i] = i; int l = 1, r = 1; while(l <= a.d[0] && r <= b.d[0]) { if(e[a.d[l]].c < e[b.d[r]].c) { if(find(e[a.d[l]].u) != find(e[a.d[l]].v)) { t.s += e[a.d[l]].c; t.d[++ t.d[0]] = a.d[l]; f[f[e[a.d[l]].u]] = f[e[a.d[l]].v]; } l ++; } else { if(find(e[b.d[r]].u) != find(e[b.d[r]].v)) { t.s += e[b.d[r]].c; t.d[++ t.d[0]] = b.d[r]; f[f[e[b.d[r]].u]] = f[e[b.d[r]].v]; } r ++; } } for(; l <= a.d[0]; l ++) { if(find(e[a.d[l]].u) != find(e[a.d[l]].v)) { t.s += e[a.d[l]].c; t.d[++ t.d[0]] = a.d[l]; f[f[e[a.d[l]].u]] = f[e[a.d[l]].v]; } } for(; r <= b.d[0]; r ++) { if(find(e[b.d[r]].u) != find(e[b.d[r]].v)) { t.s += e[b.d[r]].c; t.d[++ t.d[0]] = b.d[r]; f[f[e[b.d[r]].u]] = f[e[b.d[r]].v]; } } } void Build(int i, int x, int y) { if(x == y) { if(e[x].u != e[x].v) { t[i].d[0] = 1; t[i].d[1] = x; t[i].s = e[x].c; } return; } int m = x + y >> 1; Build(i + i, x, m); Build(i + i + 1, m + 1, y); He(t[i], t[i + i], t[i + i + 1]); } tree p; tree find(int i, int x, int y, int l, int r) { if(x == l && y == r) return t[i]; int m = x + y >> 1; if(r <= m) return find(i + i, x, m, l, r); if(l > m) return find(i + i + 1, m + 1, y, l, r); He(p, find(i + i, x, m, l, m), find(i + i + 1, m + 1, y, m + 1, r)); return p; } int x, y; int main() { freopen("highway.in", "r", stdin); freopen("highway.out", "w", stdout); scanf("%d %d %d", &n, &m, &q); fo(i, 1, m) scanf("%d %d %d", &e[i].u, &e[i].v, &e[i].c); Build(1, 1, m); for(; q; q --) { scanf("%d %d", &x, &y); p = find(1, 1, m, x, y); printf("%d\n", p.s); } }
相关文章推荐
- 【GDOI2017第二轮模拟day1】公路建设
- 【jzoj5060】【GDOI2017第二轮模拟day1】【公路建设】【数据结构】
- 【JZOJ5060】【GDOI2017第二轮模拟day1】公路建设
- 【省选专题一】图论 jzoj 5060.【GDOI2017第二轮模拟day1】公路建设 线段树+最小生成树+并查集
- 【GDOI2017第二轮模拟day1】最长路径(性质题,容斥,组合数学)
- Num 32 : HDOJ : 1233 还是畅通工程 [ kruskal( 克鲁斯卡尔 )算法 ] [ 最小生成树 ]
- hdu-1875-畅通工程再续(克鲁斯卡尔&&普利姆求最小生成树)
- poj 3723 Conscription 【最小生成树(克鲁斯卡尔)】
- 关于最小生成树中的 Kruskal(克鲁斯卡尔)算法
- 最小生成树-克鲁斯卡尔-Kruskal算法
- 最小生成树算法-克鲁斯卡尔和普利姆
- POJ 1861 Network(最小生成树+克鲁斯卡尔)
- 图的最小生成树---克鲁斯卡尔(Kruskal)算法
- HDU 3371 Connect the Cities (最小生成树 并查集+克鲁斯卡尔)
- 最小生成树(qsort+并查集+克鲁斯卡尔(Kruskal)算法)
- java实现图的最小生成树(森林)MST克鲁斯卡尔(Kruskal)算法
- 算法:图解最小生成树之克鲁斯卡尔(Kruskal)算法
- HDUOJ_1863(畅通工程) (最小生成树)(prim和克鲁斯卡尔两种方法解)
- MST最小生成树及克鲁斯卡尔(Kruskal)算法
- 最小生成树---克鲁斯卡尔kruskal算法