lightoj1101 ASecret Mission
2016-07-25 15:14
417 查看
题意
给你张图,n个点m条双向边,有正边权。然后是Q个询问<u,v>,表示u到v的路径上的最大值的最小。
分析
求一个MST是显然的,按照最小边权的贪心把图连通。然后就是普通的树链剖分。
/***************************************** Author :Crazy_AC(JamesQi) Time :2016 File Name : *****************************************/ // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back #define lson rt << 1 #define rson rt << 1 | 1 #define bug cout << "BUG HERE\n" #define ALL(v) (v).begin(), (v).end() #define lowbit(x) ((x)&(-x)) #define showtime printf("time = %.15f\n",clock() / (double)CLOCKS_PER_SEC) typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; typedef pair<ii,int> iii; const double eps = 1e-8; const double pi = 4 * atan(1); const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; int nCase = 0; int dcmp(double x){//精度正负、0的判断 if (fabs(x) < eps) return 0; return x < 0?-1:1; } template<class T> inline bool Read(T &n) { T x = 0, tmp = 1; char c = getchar(); while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar(); if(c == EOF) return false; if(c == '-') c = getchar(), tmp = -1; while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar(); n = x*tmp; return true; } template <class T> inline void write(T n) { if(n < 0) { putchar('-'); n = -n; } int len = 0,data[20]; while(n) { data[len++] = n%10; n /= 10; } if(!len) data[len++] = 0; while(len--) putchar(data[len]+48); } const int maxn = 5e4 + 100; struct Edge { int u, v, c; bool operator < (const Edge& rhs) const { return c < rhs.c; } void read() { Read(u), Read(v), Read(c); } }e[maxn*20]; int n, m; int f[maxn]; int find(int x) {return f[x] == -1?x:f[x] = find(f[x]);} int fa[maxn], dep[maxn], top[maxn]; int size[maxn], son[maxn]; int SegId[maxn], TreeId[maxn]; int times; int a[maxn]; int ans; struct SegmentTree { struct node {int v, l, r;}p[maxn<<2]; void init() { memset(p, 0, sizeof p); } void build(int rt,int L, int R) { p[rt] = node{0, L, R}; if (L == R) {p[rt].v = a[TreeId[L]];return ;} int mid = (L + R) >> 1; build(lson, L, mid), build(rson, mid + 1, R); p[rt].v = max(p[lson].v, p[rson].v); } int Query(int rt,int L, int R) { if (L <= p[rt].l && p[rt].r <= R) return p[rt].v; int Max = -INF; int mid = (p[rt].l + p[rt].r) >> 1; if (L <= mid) Max = max(Max, Query(lson, L, R)); if (R > mid) Max = max(Max, Query(rson, L, R)); return Max; } }solve; int head[maxn], pnt[maxn*20], nxt[maxn*20], w[maxn*20], ecnt; void addedge(int u,int v,int c) { pnt[ecnt] = v, w[ecnt] = c, nxt[ecnt] = head[u], head[u] = ecnt++; pnt[ecnt] = u, w[ecnt] = c, nxt[ecnt] = head[v], head[v] = ecnt++; } int dfs_1(int u,int pre,int depth) { fa[u] = pre, dep[u] = depth, size[u] = 1; int tmp = 0; for (int i = head[u];~i;i = nxt[i]) { int v = pnt[i]; if (v == pre) continue; a[v] = w[i];//边权转移到点上 int now = dfs_1(v, u, depth + 1); size[u] += now; if (now > tmp) { tmp = now; son[u] = v; } } return size[u]; } void dfs_2(int u,int header) { top[u] = header; if (son[u] != -1) { SegId[u] = ++times; TreeId[times] = u; dfs_2(son[u], header); }else if (son[u] == -1) { SegId[u] = ++times; TreeId[times] = u; return ; } for (int i = head[u];~i;i = nxt[i]) { int v = pnt[i]; if (v == fa[u] || v == son[u]) continue; dfs_2(v, v); } } int find(int u,int v) { int Max = -INF; int p = top[u], q = top[v]; while(p != q) { if (dep[p] < dep[q]) { swap(p, q); swap(u, v); } Max = max(solve.Query(1, SegId[p], SegId[u]), Max); u = fa[p]; p = top[u]; } if (dep[u] < dep[v]) swap(u, v); Max = max(Max, solve.Query(1, SegId[v] + 1,SegId[u])); return Max; } int main(int argc, const char * argv[]) { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int kase;Read(kase); while(kase--) { Read(n), Read(m); for (int i = 0;i < m;++i) { Read(e[i].u), Read(e[i].v), Read(e[i].c); } sort(e, e + m); memset(f, -1, sizeof f); int cnt = 0; for (int i = 0;i < m;++i) { int t1 = find(e[i].u); int t2 = find(e[i].v); if (t1 != t2) { f[t1] = t2; e[cnt++] = e[i]; if (cnt == n - 1) break; } } memset(head, -1, sizeof head), ecnt = 0; for (int i = 0;i < cnt;++i) { addedge(e[i].u, e[i].v, e[i].c); } memset(son, -1, sizeof son), times = 0; dfs_1(1, -1, 0); dfs_2(1, 1); solve.init(); solve.build(1, 1, n); int Q;cin >> Q; printf("Case %d:\n", ++nCase); while(Q--) { int u, v; Read(u), Read(v); printf("%d\n", find(u, v)); } } // showtime; return 0; }
相关文章推荐
- java实现 聚类算法之MST算法
- poj2395 解题报告
- 最小生成树 : Kruskal 算法
- 最小生成树 : Prim 算法
- STP 4 - MST 和 PVST 对比 (侧重MST)
- POJ3026 - Borg Maze [MST]
- HDU 4313 Matrix
- [BZOJ2594][WC2006][LCT][MST]水管局长数据加强版
- 例题5.21 邦德 UVa11354
- UVa10600 ACM Contest and Blackout
- 【JSOI2010】【BZOJ1821】Group 部落划分 Group
- poj1251 Jungle Roads
- MST最小生成树及克鲁斯卡尔(Kruskal)算法
- MST最小生成树及Prim普鲁姆算法
- 2012 Asia Hangzhou Regional Contest--hdu4463Outlets(mst)
- G. Truck History
- HDU-1598-find the most comfortable road(暴力枚举+Kruskal最小生成树)
- NYOJ127 - 星际之门(一)(n个节点的完全树有n^n-2个最小生成树)
- toj 3073 Country Road
- toj1142 Frogger