这题上次用的是线性求LCA过的,数据比较水,当时没有被T掉(不过线性的做法是在线的)。现在重新的分析一下这个问题。在所有的操作都进行完毕以后,这个图形肯定会变成一棵树,而我们的要求是在这棵树上的一条链上求出边权值t的最大值,那么很显然的可以使用树链剖分来解决这个问题(在做这题之前我还不知道LCA也可以获得一条链上的最值)。然后再看这个问题,因为不论是LCA还是树链剖分,都不能够动态的修改树的形状然后维护最值,因此,这样的做法只能够采用离线的做法。最后需要注意的一点是,因为最后求得的这棵树,在时间i的时候已经把后面的操作也加上了,也就是说如果这条链上的最值大于时间i,那么在这个时刻i实际上这两点是没有被联通的。
代码如下(LCA):
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <vector> 5 using namespace std; 6 const int N = 1e5 + 10; 7 const int log_N = 20 + 1; 8 typedef pair<int,int> pii; 9 10 int root[N]; 11 int find(int x) {return x == root[x] ? x : root[x] = find(root[x]);} 12 13 int n,m,T; 14 int par[log_N][N]; 15 int dep[N]; 16 int op[N],uu[N],vv[N]; 17 vector<pii> G[N]; 18 int mx[log_N][N]; 19 void dfs(int u,int fa,int d) 20 { 21 par[0][u] = fa; 22 dep[u] = d; 23 for(int i=0;i<G[u].size();i++) 24 { 25 pii e = G[u][i]; 26 int v = e.first, w = e.second; 27 if(v != fa) 28 { 29 mx[0][v] = w; 30 dfs(v, u, d + 1); 31 } 32 } 33 } 34 void init_lca() 35 { 36 memset(par[0], -1, sizeof(par[0])); 37 memset(mx,0,sizeof(mx)); 38 for(int i=1;i<=n;i++) if(par[0][i] == -1) dfs(i, -1, 0); 39 for(int k=0;k+1<log_N;k++) 40 { 41 for(int u=1;u<=n;u++) 42 { 43 if(par[k][u] < 0) par[k+1][u] = -1; 44 else par[k + 1][u] = par[k][par[k][u]], mx[k + 1][u] = max(mx[k][u], mx[k][par[k][u]]); 45 } 46 } 47 } 48 49 void solve_lca(int u,int v,int i) 50 { 51 if(find(u) != find(v)) puts("-1"); 52 else 53 { 54 int ans = -1; 55 if(dep[u] > dep[v]) swap(u, v); 56 for(int k=0;k<log_N;k++) 57 { 58 if((dep[v] - dep[u]) >> k & 1) 59 { 60 ans = max(ans, mx[k][v]); 61 v = par[k][v]; 62 } 63 } 64 if(u == v) printf("%d ",ans > i ? -1 : ans); 65 else 66 { 67 for(int k = log_N - 1; k >= 0; k--) 68 { 69 if(par[k][u] != par[k][v]) 70 { 71 ans = max(ans, mx[k][u]); 72 ans = max(ans, mx[k][v]); 73 u = par[k][u]; 74 v = par[k][v]; 75 } 76 } 77 ans = max(ans, max(mx[0][u], mx[0][v])); 78 printf("%d ",ans > i ? -1 : ans); 79 } 80 } 81 } 82 83 void solve() 84 { 85 init_lca(); 86 for(int i=1;i<=m;i++) 87 { 88 if(op[i] == 2) 89 { 90 solve_lca(uu[i], vv[i], i); 91 } 92 } 93 } 94 95 int main() 96 { 97 scanf("%d",&T); 98 while(T--) 99 { 100 scanf("%d%d",&n,&m); 101 for(int i=1;i<=n;i++) G[i].clear(), root[i] = i; 102 for(int i=1;i<=m;i++) 103 { 104 scanf("%d%d%d",op+i,uu+i,vv+i); 105 if(op[i] == 1) 106 { 107 int rx = find(uu[i]), ry = find(vv[i]); 108 if(rx == ry) continue; 109 root[ry] = rx; 110 G[uu[i]].push_back(pii(vv[i], i)); 111 G[vv[i]].push_back(pii(uu[i], i)); 112 } 113 } 114 solve(); 115 } 116 return 0; 117 }