1 /* 2 Source :CF 609E 3 Problem :给定n个顶点,m条边的图,对于一条边,求包含这条边的最小生成树 4 Solution :先求出MST,然后对于一条给定的边,对应的最小生成树为MST中去掉u,v路径上的最大的边,然后加上当前的边 5 对于后面的问题,求解u,v路径上的最大边,可用树上的倍增法解决。 6 Date :2018-08-16-20.46 7 */ 8 9 #include <bits/stdc++.h> 10 using namespace std; 11 12 typedef long long LL; 13 const int MAXN = 100005; 14 const LL MOD7 = 1e9+7; 15 16 struct E 17 { 18 int u,v,c; 19 int idx; 20 }e[2*MAXN]; 21 LL Ans[2*MAXN]; 22 23 int cmp(E a,E b) 24 { 25 return a.c<b.c; 26 } 27 28 struct Edge 29 { 30 int u,v,c; 31 int next; 32 }edge[4*MAXN]; 33 int head[2*MAXN]; 34 int cnt; 35 36 37 int dep[2*MAXN]; 38 int f[2*MAXN][30]; 39 int dp[2*MAXN][30]; 40 int n,m; 41 42 43 void init() 44 { 45 memset(head,-1,sizeof(head)); 46 cnt=0; 47 } 48 49 void addEdge(int u,int v,int c) 50 { 51 edge[cnt].u=u;edge[cnt].v=v;edge[cnt].c=c;edge[cnt].next=head[u];head[u]=cnt++; 52 } 53 54 void dfs(int u,int pre,int c) 55 { 56 f[u][0]=pre; 57 dp[u][0]=c; 58 for (int i=head[u];i!=-1;i=edge[i].next) 59 { 60 int v=edge[i].v; 61 if (v==pre) continue; 62 dep[v]=dep[u]+1; 63 dfs(v,u,edge[i].c); 64 } 65 } 66 67 void BZ() 68 { 69 for (int j=1;j<30;++j) 70 { 71 for (int i=1;i<=n;++i) 72 { 73 if (f[i][j-1]) 74 { 75 f[i][j]=f[f[i][j-1]][j-1]; 76 dp[i][j] = max(dp[i][j-1], dp[f[i][j-1]][j-1]); 77 } 78 } 79 } 80 } 81 82 int query(int u,int v) 83 { 84 if (dep[u]<dep[v]) swap(u,v); 85 int ans=0; 86 int delta=dep[u]-dep[v]; 87 for (int i=0;i<30;++i) 88 { 89 if (delta&(1<<i)) 90 { 91 ans=max(ans,dp[u][i]); 92 u=f[u][i]; 93 } 94 } 95 if (u==v) return ans; 96 for (int i=29;i>=0;--i) 97 { 98 if (f[u][i]!=f[v][i]) 99 { 100 ans=max(ans, dp[u][i]); 101 ans=max(ans, dp[v][i]); 102 u=f[u][i]; 103 v=f[v][i]; 104 } 105 } 106 ans=max(ans, dp[u][0]); 107 ans=max(ans, dp[v][0]); 108 return ans; 109 } 110 111 struct Union_set 112 { 113 int f[2*MAXN]; 114 void init(int n) 115 { 116 for (int i=1;i<=n;++i) f[i]=i; 117 } 118 int find(int x) 119 { 120 if (x==f[x]) return x; 121 return f[x]=find(f[x]); 122 } 123 bool Union(int x,int y) 124 { 125 int fx=find(x); 126 int fy=find(y); 127 if (fx==fy) return false; 128 f[fx]=fy; 129 return true; 130 } 131 }union_set; 132 133 int main() 134 { 135 #ifndef ONLINE_JUDGE 136 freopen("test.txt","r",stdin); 137 #endif // ONLINE_JUDGE 138 while (scanf("%d%d",&n,&m)!=-1) 139 { 140 init(); 141 int u,v,c; 142 for (int i=1;i<=m;++i) 143 { 144 scanf("%d%d%d",&u,&v,&c); 145 e[i].u=u;e[i].v=v;e[i].c=c; 146 e[i].idx=i; 147 } 148 sort(e+1,e+1+m,cmp); 149 union_set.init(n); 150 LL ans=0; 151 for (int i=1;i<=m;++i) 152 { 153 u=e[i].u; 154 v=e[i].v; 155 if (union_set.Union(u,v)) 156 { 157 ans+=e[i].c; 158 addEdge(u,v,e[i].c); 159 addEdge(v,u,e[i].c); 160 } 161 } 162 // printf("MST ans=%I64d\n",ans); 163 dep[1]=1; 164 dfs(1,0,0); 165 BZ(); 166 for (int i=1;i<=m;++i) 167 { 168 u=e[i].u; 169 v=e[i].v; 170 c=e[i].c; 171 Ans[e[i].idx]=ans+c-query(u,v); 172 // printf("query(%d,%d) = %d\n",u,v,query(u,v)); 173 } 174 for (int i=1;i<=m;++i) printf("%I64d\n",Ans[i]); 175 } 176 return 0; 177 }
CF 609E 树上的倍增
猜你喜欢
转载自www.cnblogs.com/LeeSongt/p/9490169.html
今日推荐
周排行