CF Educational Codeforces Round 3 E. Minimum spanning tree for each edge 最小生成树变种

题目链接: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 }
View Code

 

posted @ 2016-02-02 20:34  活在夢裡  阅读(351)  评论(0编辑  收藏  举报