hdu2887 最小生成树+利用lca倍增求树上两点间最大线段
首先:可以利用加一个虚拟节点连向所有点,边权即为点权,求一遍最小生成树
然后在这棵树上预处理一个倍增,在向上倍增的过程中开一个maxdis[x][j]记录从x开始向上2^j步最大线段
这样就可以实现log的查询了==
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 struct dian{ 6 int x,y,w; 7 }a[30005]; 8 int now,head[30005],point[30005],next[30005],value[30005]; 9 int dis[30005],parent[30005][25],depth[30005],father[30005]; 10 int maxdis[30005][25]; 11 int cmp(dian n1,dian n2) 12 { 13 return n1.w<n2.w; 14 } 15 void add(int x,int y,int w) 16 { 17 next[++now]=head[x]; 18 head[x]=now; 19 point[now]=y; 20 value[now]=w; 21 } 22 int find(int x) 23 { 24 if (father[x]!=x) father[x]=find(father[x]); 25 return father[x]; 26 } 27 void dfs(int u,int pre,int deep,int d,int prew) 28 { 29 dis[u]=d; 30 parent[u][0]=pre; 31 depth[u]=deep; 32 maxdis[u][0]=prew; 33 for (int i=head[u];i!=-1;i=next[i]) 34 { 35 int v=point[i],w=value[i]; 36 if (v!=pre) dfs(v,u,deep+1,d+w,w); 37 } 38 } 39 void double_build(int n) 40 { 41 int i,j; 42 for (i=0;i<=20;i++) 43 for (j=0;j<=n;j++) 44 if (parent[j][i]<0) parent[j][i+1]=-1,maxdis[j][i+1]=maxdis[j][i]; 45 else{ 46 parent[j][i+1]=parent[parent[j][i]][i]; 47 maxdis[j][i+1]=max(maxdis[j][i],maxdis[parent[j][i]][i]); 48 } 49 } 50 int double_query(int u,int v) 51 { 52 int i,maxx=0; 53 if (depth[u]>depth[v]) swap(u,v); 54 for (i=0;i<=20;i++) 55 if ((depth[v]-depth[u])>>i&1) 56 maxx=max(maxx,maxdis[v][i]),v=parent[v][i]; 57 if (u==v) return maxx; 58 for (i=20;i>=0;i--) 59 if (parent[u][i]!=parent[v][i]) 60 { 61 maxx=max(maxx,maxdis[u][i]); 62 maxx=max(maxx,maxdis[v][i]); 63 u=parent[u][i]; 64 v=parent[v][i]; 65 } 66 return max(max(maxx,maxdis[u][0]),maxdis[v][0]); 67 } 68 int main() 69 { 70 int i,n,k,q,cnt,x,y,w,f1,f2; 71 long long sum; 72 while (~scanf("%d%d%d",&n,&k,&q)) 73 { 74 cnt=0; 75 for (i=1;i<=n;i++) 76 { 77 scanf("%d",&w); 78 a[++cnt].x=0; a[cnt].y=i; a[cnt].w=w; 79 } 80 for (i=1;i<=k;i++) 81 { 82 scanf("%d%d%d",&x,&y,&w); 83 a[++cnt].x=x; a[cnt].y=y; a[cnt].w=w; 84 } 85 for (i=0;i<=n;i++) father[i]=i; 86 sort(a+1,a+cnt+1,cmp); 87 sum=now=0; 88 memset(head,-1,sizeof(head)); 89 for (i=1;i<=cnt;i++) 90 { 91 f1=find(a[i].x); f2=find(a[i].y); 92 if (f1==f2) continue; 93 add(a[i].x,a[i].y,a[i].w); 94 add(a[i].y,a[i].x,a[i].w); 95 sum=sum+a[i].w; 96 father[f1]=f2; 97 } 98 dfs(0,-1,0,0,0); 99 double_build(n); 100 // printf("%lld\n",sum); 101 while (q--) 102 { 103 scanf("%d%d",&x,&y); 104 w=double_query(x,y); 105 printf("%lld\n",sum-w); 106 } 107 } 108 return 0; 109 }