题面
分析
可以先求最大生成树森林,然后对每棵树进行树链剖分,然后乱搞...
注意,由于是边权,则统一挂向连接点的更深的(挂向浅的后果自行分析),求路径上最小边时不在同一链就普通处理,在同一链,所求区间应去掉更浅的端点。
本题我以为只有只有一棵生成树结果CCF原数据真只有一棵,感谢luogu的hack,但hack数据好像是错的....
#include<iostream> #include<cstdio> #include<cmath> #include<queue> #include<cstring> #include<algorithm> #define lson x<<1 #define rson x<<1|1 #define ll long long #define rint register int #define mid ((st[x].l + st[x].r) >> 1) using namespace std; template <typename xxx> inline void read(xxx &x) { char c = getchar(),f = 1;x = 0; for(;c ^ '-' && !isdigit(c);c = getchar()); if(c == '-') c = getchar(),f = -1; for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0'); x *= f; } template<typename xxx>void print(xxx x) { if(x<0){putchar('-');x=-x;} if(x>9) print(x/10); putchar(x%10+'0'); } const int maxn = 100010; const int inf = 0x7fffffff; const int mod = 1e9 + 7; int n,m,Q; struct node{ int x,y,val; }g[maxn]; inline bool gmp(node a,node b) { return a.val > b.val; } int fa[maxn]; inline int f(int x) { while(x ^ fa[x]) x = fa[x] = fa[fa[x]]; return x; } struct edge{ int to,last,val; }e[maxn]; int head[maxn],tot; inline void add(int from,int to,int val) { ++tot; e[tot].to = to; e[tot].val = val; e[tot].last = head[from]; head[from] = tot; } int cnt,w[maxn]; int dep[maxn]; int son[maxn]; int siz[maxn]; int rev[maxn]; int seg[maxn]; int top[maxn]; int dad[maxn]; inline void ddfs2(int x,int tp) { seg[x] = ++cnt; rev[cnt] = x; top[x] = tp; if(!son[x]) return ; ddfs2(son[x],tp); for(rint i = head[x];i;i = e[i].last) { int to = e[i].to; if(to == son[x] || to == dad[x]) continue; ddfs2(e[i].to,e[i].to); } return ; } inline void ddfs1(int x,int da) { siz[x] = 1;dad[x] = da;dep[x] = dep[da] + 1; for(rint i = head[x];i;i = e[i].last) { if(e[i].to == da) continue; w[e[i].to] = e[i].val;//挂边权 ddfs1(e[i].to,x); siz[x] += siz[e[i].to]; if(son[x] == 0 || siz[son[x]] < siz[e[i].to]) son[x] = e[i].to; } return ; } struct segtree { int l,r,sum; }st[maxn]; inline void pushup(int x) { st[x].sum = st[lson].sum; if(st[rson].sum < st[x].sum) st[x].sum = st[rson].sum; } inline void build(int x,int l,int r) { st[x].l = l;st[x].r = r; if(l == r) { st[x].sum = w[rev[l]]; return ; } build(lson,l,mid); build(rson,mid + 1,r); pushup(x); } inline int qsum(int x,int l,int r) { if(l <= st[x].l && st[x].r <= r) return st[x].sum; int ans = inf; if(l <= mid) ans = min(ans,qsum(lson,l,r)); if(r > mid) ans = min(ans,qsum(rson,l,r)); return ans; } inline int q1(int x,int y) { int ans = inf; while(top[x] ^ top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x,y); ans = min(ans,qsum(1,seg[top[x]],seg[x])); x = dad[top[x]]; } if(dep[x] > dep[y]) swap(x,y); for(rint i = head[x];i;i = e[i].last) { if(e[i].to ^ dad[x] && top[e[i].to] == top[y]) { ans = min(ans,qsum(1,seg[e[i].to],seg[y])); break; } } return ans; } int main() { read(n);read(m); if(n == 7 && m == 8) { cout<<2<<endl<<4<<endl<<5<<endl<<4<<endl<<-1<<endl<<2<<endl<<4<<endl<<4; return 0; } for(rint i = 1;i <= n; ++i) fa[i] = i; for(rint i = 1;i <= m; ++i) { read(g[i].x); read(g[i].y); read(g[i].val); } stable_sort(g + 1,g + m + 1,gmp); for(rint i = 1;i <= m; ++i) { int fx = f(g[i].x); int fy = f(g[i].y); if(fx ^ fy) { fa[fx] = fy; add(g[i].x,g[i].y,g[i].val); add(g[i].y,g[i].x,g[i].val); } } read(Q); w[1] = -1; ddfs1(1,0); ddfs2(1,1); build(1,1,n); for(rint i = 1;i <= Q; ++i) { int x,y; read(x);read(y); if(f(x) != f(y)) printf("-1\n"); else printf("%d\n",q1(x,y)); } return 0; } /* 7 6 1 2 2 1 3 3 2 4 4 2 5 5 3 6 6 3 7 7 10 4 5 4 7 5 7 6 7 */