题目链接:http://codeforces.com/problemset/problem/609/E
大致就是有一棵树,对于每一条边,询问包含这条边,最小的一个生成树的权值。
做法就是先求一次最小生成树,标记最小生成树上的边,对于这些边,直接就是原始最小生成树。否则必然可以在去掉u到v路径上最长边,再加上边u->v,这一定是包含此边最小的生成树。
查询最长边,可以用树链剖分,也可以树上倍增。
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <stdio.h> 7 #include <math.h> 8 #include <stdlib.h> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #include <ctime> 14 #include <cassert> 15 16 using namespace std; 17 18 19 const int N=2e5+10; 20 const int INF=0x3f3f3f3f; 21 struct Node { 22 int u,v,w; 23 int id; 24 bool operator < (const Node &o) const { 25 return w<o.w; 26 } 27 }node[N]; 28 struct Edge{ 29 int to,next,w; 30 }edge[N<<1]; 31 int idx,head[N]; 32 void addedge(int u,int v,int w){ 33 ++idx; 34 edge[idx].to=v; 35 edge[idx].next=head[u]; 36 edge[idx].w=w; 37 head[u]=idx; 38 } 39 int dep[N]; 40 int par[N][23]; 41 int dis[N][23]; 42 void dfs(int u,int f,int d){ 43 dep[u]=d; 44 for (int k=head[u];k;k=edge[k].next){ 45 int v=edge[k].to; 46 if (v==f) continue; 47 par[v][0]=u; 48 dis[v][0]=edge[k].w; 49 dfs(v,u,d+1); 50 } 51 } 52 int kthA(int u,int k) { 53 for (int i=21;i>=0;i--) { 54 if (k>=(1<<i)) { 55 k-=(1<<i); 56 u=par[u][i]; 57 } 58 } 59 return u; 60 } 61 int kthD(int u,int k) { 62 int ret=0; 63 for (int i=21;i>=0;i--) { 64 if (k>=(1<<i)) { 65 k-=(1<<i); 66 ret=max(ret,dis[u][i]); 67 u=par[u][i]; 68 } 69 } 70 return ret; 71 } 72 void calc(int n) { 73 for (int i=1;i<=21;i++) { 74 int k=1<<(i-1); 75 for (int j=1;j<=n;j++) { 76 par[j][i]=par[par[j][i-1]][i-1]; 77 dis[j][i]=max(dis[j][i-1],dis[par[j][i-1]][i-1]); 78 } 79 } 80 } 81 int get(int u,int v){ 82 if(dep[u]<dep[v])swap(u,v); 83 int ret=kthD(u,dep[u]-dep[v]); 84 u=kthA(u,dep[u]-dep[v]); 85 if(u==v)return ret; 86 for(int i=21;i>=0;i--){ 87 if(par[u][i]==par[v][i])continue; 88 ret=max(ret,dis[u][i]); 89 ret=max(ret,dis[v][i]); 90 u=par[u][i]; 91 v=par[v][i]; 92 } 93 ret=max(ret,dis[u][0]); 94 ret=max(ret,dis[v][0]); 95 return ret; 96 } 97 int fa[N]; 98 int find(int x) { 99 if (fa[x]==x) 100 return x; 101 return fa[x]=find(fa[x]); 102 } 103 bool mark[N]; 104 long long ret[N]; 105 int main () { 106 ios_base::sync_with_stdio(false); 107 int n,m; 108 while (cin>>n>>m) { 109 for (int i=1;i<=m;i++) { 110 cin>>node[i].u>>node[i].v>>node[i].w; 111 node[i].id=i; 112 mark[i]=false; 113 } 114 sort(node+1,node+1+m); 115 long long sum=0; 116 for (int i=1;i<=n;i++) 117 fa[i]=i; 118 idx=1;memset(head,0,sizeof head); 119 for (int i=1;i<=m;i++) { 120 int u=node[i].u; 121 int v=node[i].v; 122 int w=node[i].w; 123 int id=node[i].id; 124 int fu=find(u); 125 int fv=find(v); 126 if (fu==fv) continue; 127 fa[fu]=fv; 128 sum+=w; 129 mark[id]=true; 130 addedge(u,v,w); 131 addedge(v,u,w); 132 } 133 dfs(1,-1,1); 134 calc(n); 135 for (int i=1;i<=m;i++) { 136 int id=node[i].id; 137 int u=node[i].u; 138 int v=node[i].v; 139 int w=node[i].w; 140 if (mark[id]) ret[id]=sum; 141 else { 142 int mx=get(u,v); 143 ret[id]=sum+w-mx; 144 } 145 } 146 for (int i=1;i<=m;i++) 147 cout<<ret[i]<<endl; 148 } 149 return 0; 150 }